Skip to content

Commit 74bbb21

Browse files
author
Parva9eh
authored
Update README.markdown
Hello, My name is Parvaneh. I am taking a writing course in the field of Computer Science. For an assignment, I need to edit some relevant documents and share the result. I hope you like my revisions.
1 parent 9d8f20d commit 74bbb21

File tree

1 file changed

+36
-36
lines changed

1 file changed

+36
-36
lines changed

Merge Sort/README.markdown

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,40 @@
22

33
Goal: Sort an array from low to high (or high to low)
44

5-
Invented in 1945 by John von Neumann, merge sort is a fairly efficient sorting algorithm with a best, worst, and average time complexity of **O(n log n)**.
5+
Invented in 1945 by John von Neumann, merge-sort is an efficient algorithm with a best, worst, and average time complexity of **O(n log n)**.
66

7-
The idea behind merge sort is to **divide and conquer**: to divide a big problem into smaller problems and solving many small problems instead of solving a big one. I think of merge sort as **split first** and **merge after**.
7+
The merge-sort algorithm uses the **divide and conquer** approach which is to divide a big problem into smaller problems and solve them. I think of the merge-sort algorithm as **split first** and **merge after**.
88

9-
Assume you're given an array of *n* numbers and you need to put them in the right order. The merge sort algorithm works as follows:
9+
Assume you need to sort an array of *n* numbers in the right order. The merge-sort algorithm works as follows:
1010

11-
- Put the numbers in a pile. The pile is unsorted.
12-
- Split the pile into 2. Now you have **two unsorted piles** of numbers.
13-
- Keep splitting the resulting piles until you can't split anymore. In the end, you will have *n* piles with 1 number in each pile.
14-
- Begin to **merge** the piles together by sequentially pairing a pile with another pile. During each merge, you put the contents in sorted order. This is fairly easy because each individual pile is already sorted.
11+
- Put the numbers in an unsorted pile.
12+
- Split the pile into two. Now, you have **two unsorted piles** of numbers.
13+
- Keep splitting the resulting piles until you cannot split anymore. In the end, you will have *n* piles with one number in each pile.
14+
- Begin to **merge** the piles together by pairing them sequentially. During each merge, put the contents in sorted order. This is fairly easy because each individual pile is already sorted.
1515

1616
## An example
1717

1818
### Splitting
1919

20-
Let's say the numbers to sort are `[2, 1, 5, 4, 9]`. This is your unsorted pile. The goal is to keep splitting the pile until you can't split anymore.
20+
Assume you are given an array of *n* numbers as`[2, 1, 5, 4, 9]`. This is an unsorted pile. The goal is to keep splitting the pile until you cannot split anymore.
2121

22-
First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes you can!
22+
First, split the array into two halves: `[2, 1]` and `[5, 4, 9]`. Can you keep splitting them? Yes, you can!
2323

24-
Focus on the left pile. `[2, 1]` will split into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile.
24+
Focus on the left pile. Split`[2, 1]` into `[2]` and `[1]`. Can you keep splitting them? No. Time to check the other pile.
2525

26-
`[5, 4, 9]` splits to `[5]` and `[4, 9]`. Unsurprisingly, `[5]` can't be split anymore, but `[4, 9]` splits into `[4]` and `[9]`.
26+
Split `[5, 4, 9]` into `[5]` and `[4, 9]`. Unsurprisingly, `[5]` cannot be split anymore, but `[4, 9]` can be split into `[4]` and `[9]`.
2727

2828
The splitting process ends with the following piles: `[2]` `[1]` `[5]` `[4]` `[9]`. Notice that each pile consists of just one element.
2929

3030
### Merging
3131

32-
Now that you've split the array, you'll **merge** the piles together **while sorting them**. Remember, the idea is to solve many small problems rather than a big one. For each merge iteration you'll only be concerned at merging one pile with another.
32+
Now that you have split the array, you should **merge** the piles together **while sorting them**. Remember, the idea is to solve many small problems rather than a big one. For each merge iteration, you must be concerned at merging one pile with another.
3333

34-
Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1, 2]` and `[4, 5]` and `[9]`. Since `[9]` is the odd one out, you can't merge it with anything during this pass.
34+
Given the piles `[2]` `[1]` `[5]` `[4]` `[9]`, the first pass will result in `[1, 2]` and `[4, 5]` and `[9]`. Since `[9]` is the odd one out, you cannot merge it with anything during this pass.
3535

36-
The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again since it's the odd one out.
36+
The next pass will merge `[1, 2]` and `[4, 5]` together. This results in `[1, 2, 4, 5]`, with the `[9]` left out again because it is the odd one out.
3737

38-
You're left with only two piles and `[9]` finally gets its chance to merge, resulting in the sorted array `[1, 2, 4, 5, 9]`.
38+
You are left with only two piles and `[9]`, finally gets its chance to merge, resulting in the sorted array as `[1, 2, 4, 5, 9]`.
3939

4040
## Top-down implementation
4141

@@ -57,15 +57,15 @@ func mergeSort(_ array: [Int]) -> [Int] {
5757

5858
A step-by-step explanation of how the code works:
5959

60-
1. If the array is empty or only contains a single element, there's no way to split it into smaller pieces. You'll just return the array.
60+
1. If the array is empty or contains a single element, there is no way to split it into smaller pieces. You must just return the array.
6161

6262
2. Find the middle index.
6363

6464
3. Using the middle index from the previous step, recursively split the left side of the array.
6565

66-
4. Also recursively split the right side of the array.
66+
4. Also, recursively split the right side of the array.
6767

68-
5. Finally, merge all the values together, making sure that it's always sorted.
68+
5. Finally, merge all the values together, making sure that it is always sorted.
6969

7070
Here's the merging algorithm:
7171

@@ -109,15 +109,15 @@ func merge(leftPile: [Int], rightPile: [Int]) -> [Int] {
109109
}
110110
```
111111

112-
This method may look scary but it is quite straightforward:
112+
This method may look scary, but it is quite straightforward:
113113

114114
1. You need two indexes to keep track of your progress for the two arrays while merging.
115115

116-
2. This is the merged array. It's empty right now, but you'll build it up in subsequent steps by appending elements from the other arrays.
116+
2. This is the merged array. It is empty right now, but you will build it up in subsequent steps by appending elements from the other arrays.
117117

118-
3. This while loop will compare the elements from the left and right sides, and append them to the `orderedPile` while making sure that the result stays in order.
118+
3. This while-loop will compare the elements from the left and right sides and append them into the `orderedPile` while making sure that the result stays in order.
119119

120-
4. If control exits from the previous while loop, it means that either `leftPile` or `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there's no more to append.
120+
4. If control exits from the previous while-loop, it means that either the `leftPile` or the `rightPile` has its contents completely merged into the `orderedPile`. At this point, you no longer need to do comparisons. Just append the rest of the contents of the other array until there is no more to append.
121121

122122
As an example of how `merge()` works, suppose that we have the following piles: `leftPile = [1, 7, 8]` and `rightPile = [3, 6, 9]`. Note that each of these piles is individually sorted already -- that is always true with merge sort. These are merged into one larger sorted pile in the following steps:
123123

@@ -131,13 +131,13 @@ The left index, here represented as `l`, points at the first item from the left
131131
[ 1, 7, 8 ] [ 3, 6, 9 ] [ 1 ]
132132
-->l r
133133

134-
Now `l` points at `7` but `r` is still at `3`. We add the smallest item to the ordered pile, so that's `3`. The situation is now:
134+
Now `l` points at `7` but `r` is still at `3`. We add the smallest item to the ordered pile, so that is `3`. The situation is now:
135135

136136
leftPile rightPile orderedPile
137137
[ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3 ]
138138
l -->r
139139

140-
This process repeats. At each step we pick the smallest item from either `leftPile` or `rightPile` and add it to `orderedPile`:
140+
This process repeats. At each step, we pick the smallest item from either the `leftPile` or the `rightPile` and add the item into the `orderedPile`:
141141

142142
leftPile rightPile orderedPile
143143
[ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6 ]
@@ -151,13 +151,13 @@ This process repeats. At each step we pick the smallest item from either `leftPi
151151
[ 1, 7, 8 ] [ 3, 6, 9 ] [ 1, 3, 6, 7, 8 ]
152152
-->l r
153153

154-
Now there are no more items in the left pile. We simply add the remaining items from the right pile, and we're done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`.
154+
Now, there are no more items in the left pile. We simply add the remaining items from the right pile, and we are done. The merged pile is `[ 1, 3, 6, 7, 8, 9 ]`.
155155

156-
Notice that this algorithm is very simple: it moves from left-to-right through the two piles and at every step picks the smallest item. This works because we guarantee that each of the piles is already sorted.
156+
Notice that, this algorithm is very simple: it moves from left-to-right through the two piles and at every step picks the smallest item. This works because we guarantee that each of the piles is already sorted.
157157

158158
## Bottom-up implementation
159159

160-
The implementation of merge sort you've seen so far is called "top-down" because it first splits the array into smaller piles and then merges them. When sorting an array (as opposed to, say, a linked list) you can actually skip the splitting step and immediately start merging the individual array elements. This is called the "bottom-up" approach.
160+
The implementation of the merge-sort algorithm you have seen so far is called the "top-down" approach because it first splits the array into smaller piles and then merges them. When sorting an array (as opposed to, say, a linked list) you can actually skip the splitting step and immediately start merging the individual array elements. This is called the "bottom-up" approach.
161161

162162
Time to step up the game a little. :-) Here is a complete bottom-up implementation in Swift:
163163

@@ -212,19 +212,19 @@ func mergeSortBottomUp<T>(_ a: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] {
212212
}
213213
```
214214

215-
It looks a lot more intimidating than the top-down version but notice that the main body includes the same three `while` loops from `merge()`.
215+
It looks a lot more intimidating than the top-down version, but notice that the main body includes the same three `while` loops from `merge()`.
216216

217217
Notable points:
218218

219-
1. Merge sort needs a temporary working array because you can't merge the left and right piles and at the same time overwrite their contents. But allocating a new array for each merge is wasteful. Therefore, we're using two working arrays and we'll switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, `z[1 - d]` is used for writing. This is called *double-buffering*.
219+
1. The Merge-sort algorithm needs a temporary working array because you cannot merge the left and right piles and at the same time overwrite their contents. Because allocating a new array for each merge is wasteful, we are using two working arrays, and we will switch between them using the value of `d`, which is either 0 or 1. The array `z[d]` is used for reading, and `z[1 - d]` is used for writing. This is called *double-buffering*.
220220

221-
2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of 1 element each, then it merges piles of 2 elements each, then piles of 4 elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration we multiply it by 2. So this outer loop determines the size of the piles being merged. And in each step, the subarrays to merge become larger.
221+
2. Conceptually, the bottom-up version works the same way as the top-down version. First, it merges small piles of one element each, then it merges piles of two elements each, then piles of four elements each, and so on. The size of the pile is given by `width`. Initially, `width` is `1` but at the end of each loop iteration, we multiply it by two, so this outer loop determines the size of the piles being merged, and the subarrays to merge become larger in each step.
222222

223223
3. The inner loop steps through the piles and merges each pair of piles into a larger one. The result is written in the array given by `z[1 - d]`.
224224

225-
4. This is the same logic as in the top-down version. The main difference is that we're using double-buffering, so values are read from `z[d]` and written into `z[1 - d]`. It also uses an `isOrderedBefore` function to compare the elements rather than just `<`, so this merge sort is generic and you can use it to sort any kind of object you want.
225+
4. This is the same logic as in the top-down version. The main difference is that we're using double-buffering, so values are read from `z[d]` and written into `z[1 - d]`. It also uses an `isOrderedBefore` function to compare the elements rather than just `<`, so this merge-sort algorithm is generic, and you can use it to sort any kind of object you want.
226226

227-
5. At this point, the piles of size `width` from array `z[d]` have been merged into larger piles of size `width * 2` in array `z[1 - d]`. Here we swap the active array, so that in the next step we'll read from the new piles we've just created.
227+
5. At this point, the piles of size `width` from array `z[d]` have been merged into larger piles of size `width * 2` in array `z[1 - d]`. Here, we swap the active array, so that in the next step we'll read from the new piles we have just created.
228228

229229
This function is generic, so you can use it to sort any type you desire, as long as you provide a proper `isOrderedBefore` closure to compare the elements.
230230

@@ -237,15 +237,15 @@ mergeSortBottomUp(array, <) // [1, 2, 4, 5, 9]
237237

238238
## Performance
239239

240-
The speed of merge sort is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do.
240+
The speed of the merge-sort algorithm is dependent on the size of the array it needs to sort. The larger the array, the more work it needs to do.
241241

242-
Whether or not the initial array is sorted already doesn't affect the speed of merge sort since you'll be doing the same amount splits and comparisons regardless of the initial order of the elements.
242+
Whether or not the initial array is sorted already doesnot affect the speed of the merge-sort algorithm since you will be doing the same amount splits and comparisons regardless of the initial order of the elements.
243243

244244
Therefore, the time complexity for the best, worst, and average case will always be **O(n log n)**.
245245

246-
A disadvantage of merge sort is that it needs a temporary "working" array equal in size to the array being sorted. It is not an **in-place** sort, unlike for example [quicksort](../Quicksort/).
246+
A disadvantage of the merge-sort algorithm is that it needs a temporary "working" array equal in size to the array being sorted. It is not an **in-place** sort, unlike for example [quicksort](../Quicksort/).
247247

248-
Most implementations of merge sort produce a **stable** sort. This means that array elements that have identical sort keys will stay in the same order relative to each other after sorting. This is not important for simple values such as numbers or strings, but it can be an issue when sorting more complex objects.
248+
Most implementations of the merge-sort algorithm produce a **stable** sort. This means that array elements that have identical sort keys will stay in the same order relative to each other after sorting. This is not important for simple values such as numbers or strings, but it can be an issue when sorting more complex objects.
249249

250250
## See also
251251

0 commit comments

Comments
 (0)