Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 25f83ac

Browse files
committed
Update 05.Array-Merge-Sort.md
1 parent eab4910 commit 25f83ac

File tree

1 file changed

+56
-25
lines changed

1 file changed

+56
-25
lines changed

‎Contents/01.Array/02.Array-Sort/05.Array-Merge-Sort.md‎

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,80 @@
11
## 1. 归并排序算法思想
22

3-
> 归并排序(Merge Sort)基本思想:
3+
> **归并排序(Merge Sort)基本思想**:
44
>
55
> 采用经典的分治策略,先递归地将当前序列平均分成两半。然后将有序序列两两合并,最终合并成一个有序序列。
66
77
## 2. 归并排序算法步骤
88

9-
- 初始时,将待排序序列中的 `n` 个记录看成 `n` 个有序子序列(每个子序列总是有序的),每个子序列的长度均为 `1`
10-
- 把当前序列组中有序子序列两两归并,完成一遍之后序列组里的排序序列个数减半,每个子序列的长度加倍。
11-
- 对长度加倍的有序子序列重复上面的操作,最终得到一个长度为 `n` 的有序序列。
9+
1. **分割过程**:先递归地将当前序列平均分成两半,直到子序列长度为 `1`
10+
1. 找到序列中心位置 `mid`,从中心位置将序列分成左右两个子序列 `left_arr``right_arr`
11+
2. 对左右两个子序列 `left_arr``right_arr` 分别进行递归分割。
12+
3. 最终将数组分割为 `n` 个长度均为 `1` 的有序子序列。
13+
2. **归并过程**:从长度为 `1` 的有序子序列开始,依次进行两两归并,直到合并成一个长度为 `n` 的有序序列。
14+
1. 使用数组变量 `arr` 存放归并后的有序数组。
15+
2. 使用两个指针 `left_i``right_i` 分别指向两个有序子序列 `left_arr``right_arr` 的开始位置。
16+
3. 比较两个指针指向的元素,将两个有序子序列中较小元素依次存入到结果数组 `arr` 中,并将指针移动到下一位置。
17+
4. 重复步骤 `3`,直到某一指针到达子序列末尾。
18+
5. 将另一个子序列中的剩余元素存入到结果数组 `arr` 中。
19+
6. 返回归并后的有序数组 `arr`
1220

1321
## 3. 归并排序动画演示
1422

15-
![](https://www.runoob.com/wp-content/uploads/2019/03/mergeSort.gif)
23+
![](https://qcdn.itcharge.cn/images/20220816161220.gif)
24+
25+
1. 初始序列为 `[6, 2, 1, 3, 7, 5, 4, 8]`
26+
2. 将序列分解为 `[6, 2, 1, 3]`,`[7, 5, 4, 8]`
27+
3. 将序列分解为 `[6, 2]`,`[1, 3]`,`[7, 5]`,`[4, 8]`
28+
4. 将序列分为为 `[6]`,`[2]`,`[1]`,`[3]`,`[7]`,`[5]`,`[4]`,`[8]`
29+
5. 将序列看做是 `8` 个长度为 `1` 的子序列,即 `[6]`,`[2]`,`[1]`,`[3]`,`[7]`,`[5]`,`[4]`,`[8]`
30+
6.`1` 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:`[2, 6]`,`[1, 3]`,`[5, 7]`,`[4, 8]`
31+
7.`2` 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:`[1, 2, 3, 6]`,`[4, 5, 7, 8]`
32+
8.`3` 趟排序:将子序列中的有序子序列两两归并,归并后的子序列为:`[1, 2, 3, 4, 5, 6, 7, 8]`。得到长度为 `n` 的有序序列,排序结束。
1633

1734
## 4. 归并排序算法分析
1835

19-
- 归并排序算法的时间复杂度等于归并趟数与每一趟归并的时间复杂度成绩。子算法 `merge(left_arr, right_arr):` 的时间复杂度是 $O(n),ドル因此,归并排序算法总的时间复杂度为 $O(nlog_2n)$。
20-
- 归并排序方法需要用到与参加排序的序列同样大小的辅助空间。因此算法的空间复杂度为 $O(n)$。
21-
- 因为在两个有序子序列的归并过程中,如果两个有序序列中出现相同元素,`merge(left_arr, right_arr):` 算法能够使前一个序列中那个相同元素先被复制,从而确保这两个元素的相对次序不发生改变。所以归并排序算法是 **稳定排序算法**
36+
- **时间复杂度**:$O(n \times \log_2n)$。归并排序算法的时间复杂度等于归并趟数与每一趟归并的时间复杂度乘积。子算法 `merge(left_arr, right_arr):` 的时间复杂度是 $O(n),ドル因此,归并排序算法总的时间复杂度为 $O(n \times \log_2 n)$。
37+
- **空间复杂度**:$O(n)$。归并排序方法需要用到与参加排序的序列同样大小的辅助空间。因此算法的空间复杂度为 $O(n)$。
38+
- **排序稳定性**:归并排序算法是一种 **稳定排序算法**
39+
- 因为在两个有序子序列的归并过程中,如果两个有序序列中出现相同元素,`merge(left_arr, right_arr):` 算法能够使前一个序列中那个相同元素先被复制,从而确保这两个元素的相对次序不发生改变。
40+
2241

2342
## 5. 归并排序代码实现
2443

2544
```Python
2645
class Solution:
27-
def merge(self, left_arr, right_arr):
46+
def merge(self, left_arr, right_arr):# 归并过程
2847
arr = []
29-
while left_arr and right_arr:
30-
if left_arr[0] <= right_arr[0]:
31-
arr.append(left_arr.pop(0))
48+
left_i, right_i = 0, 0
49+
while left_i < len(left_arr) and right_i < len(right_arr):
50+
# 将两个有序子序列中较小元素依次插入到结果数组中
51+
if left_arr[left_i] < right_arr[right_i]:
52+
arr.append(left_arr[left_i])
53+
left_i += 1
3254
else:
33-
arr.append(right_arr.pop(0))
34-
while left_arr:
35-
arr.append(left_arr.pop(0))
36-
while right_arr:
37-
arr.append(right_arr.pop(0))
38-
return arr
39-
40-
def mergeSort(self, arr):
41-
size = len(arr)
42-
if size < 2:
55+
arr.append(right_arr[right_i])
56+
right_i += 1
57+
58+
while left_i < len(left_arr):
59+
# 如果左子序列有剩余元素,则将其插入到结果数组中
60+
arr.append(left_arr[left_i])
61+
left_i += 1
62+
63+
while right_i < len(right_arr):
64+
# 如果右子序列有剩余元素,则将其插入到结果数组中
65+
arr.append(right_arr[right_i])
66+
right_i += 1
67+
68+
return arr # 返回排好序的结果数组
69+
70+
def mergeSort(self, arr): # 分割过程
71+
if len(arr) <= 1: # 数组元素个数小于等于 1 时,直接返回原数组
4372
return arr
44-
mid = len(arr) // 2
45-
left_arr, right_arr = arr[0: mid], arr[mid:]
46-
return self.merge(self.mergeSort(left_arr), self.mergeSort(right_arr))
73+
74+
mid = len(arr) // 2 # 将数组从中间位置分为左右两个数组。
75+
left_arr = self.mergeSort(arr[0: mid]) # 递归将左子序列进行分割和排序
76+
right_arr = self.mergeSort(arr[mid:]) # 递归将右子序列进行分割和排序
77+
return self.merge(left_arr, right_arr) # 把当前序列组中有序子序列逐层向上,进行两两合并。
4778

4879
def sortArray(self, nums: List[int]) -> List[int]:
4980
return self.mergeSort(nums)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /