数据结构与算法:归并排序(原理讲解+python实现)

归并排序

归并排序是一种常见并且广泛运用的排序算法。由于其采用了二叉树层级的理念从而降低时间复杂度 充分提升了性能。常见的我们会运用递归来写归并排序的代码 其实通过迭代的方式来实现归并排序不失为一种好的方式。

原理讲解

归并排序基于分治策略(Divide and Conquer Stretegy)实现。分:先将要排序长度为n的列表或者数组折中分成两个子列表或者数组长度分别为(n/2) 第二次则分别将子序列分成总共4个子序列 每个子序列长度为(n/4) 以此继续分下去,直到子序列只剩下1个元素不能再分而停止。治:将最后分成的n个元素开始逐级合并,第一层治策略是将分策略最后一层得到的元素根据分策略逐个“修补”起来,俗话说就是分策略的逆过程。如图所示:

Python实现

 1 def mergeSort(a, l, r):
 2     tmp = [0 for _ in range(len(a))]  # 开辟一个与列表a相同长度的临时列表空间
 3     sort(a, l, r, tmp)
 4 
 5 def sort(a, l, r, tmp):
 6     if l < r:
 7         mid = (l + r)//2
 8         sort(a, l, mid, tmp)  # 左边归并排序 使左边子序列有序
 9         sort(a, mid+1, r, tmp)  # 右边归并排序 使右边子序列有序
10         merge(a, l, mid, r, tmp)  # 将左右两个有序的子序列合并操作
11 
12 def merge(a, l, mid, r, tmp):
13     t = 0
14     i = l
15     j = mid+1
16     while i <= mid and j <= r:
17         if a[i] <= a[j]:
18             tmp[t] = a[i]; t+=1; i+=1
19         else:
20             tmp[t] = a[j]; t+=1; j+=1
21 
22     while i <= mid:  # 右子序列比较完没有元素后 将左子序列剩下的添加临时列表后面
23         tmp[t] = a[i]; t+=1; i+=1
24 
25     while j <= r:  # 左子序列比较完没有元素后 将右子序列剩下的添加临时列表后面
26         tmp[t] = a[j]; t+=1; j+=1
27 
28     t = 0
29     while l <= r:  # 将临时列表中的数复制到原来数组当中
30         a[l] = tmp[t]; l+=1; t+=1
31 
32 if __name__ == '__main__':
33     a = [4, 2, 7, 8, 1, 3, 5, 6]
34     r = len(a)-1
35     l = 0
36     mergeSort(a, l, r)
37     print(a)

时间、空间复杂度 稳定性分析

时间复杂度:归并排序由于运用了二叉树的策略所以在分策略上是logn的时间复杂度,治策略每一层都必须比较所以n个元素, 总共有n层所以最后的时间复杂度是O(nlogn)。它不受待排序列表完全逆序的影响所以平均时间复杂度是O(nlogn)。

空间复杂度:过程开辟了长度为n的临时空间 所以空间复杂度是O(n)

稳定性分析:当左右子序列比较的两个元素相等时,左子序列的相同元素为先加入到临时序列中 所以相同元素的顺序在排序之后未发生改变 ,归并排序是稳定性排序。

总结

各种排序算法都有其自身的不可替代性,在实际运用的过程中,特别是数量巨大时,一定要结合数据的性质本身和排序算法本身来决定要用何种算法。

 

posted @ 2021-01-29 11:37  小和尚写代码  阅读(388)  评论(0编辑  收藏  举报