归并排序
思路:
一. 分而治之
先拆后合并,拆分成一个元素一个元素
1.拆分
分2组,2组分4组…直到分成数组每个元素都是单着的
2.然后合并
2个元素合并,比较大小,小的在前,依此类推
然后两个一组和另外两个一组比较排序
然后4个一组排序比较
…
最后全部排序
二. 递归
mid = n // 2
拆分和合并生成的数组是对应的,可以视为merge_sort()后返回的结果是对应的 同样大小的有序数组,
left_list = merge_sort(a[:mid])
right_list = merge_sort(a[mid:])
合并比较具体实现:
如何进行合并比较:
1. 先定义一个列表 list ,存储排序后的结果
用途:用来存储左右两边排序后的结果,将小的按顺序append进来
2.拆分后的数组和指针声明
按左右两个部分来 比如左边列表为 left 右边列表为 right
设置左边指针和右边指针下标都为0
3.比较 left[0] 和right [0]
(1)如果 left[0] < right [0] , list 就 append 小的数 left[0]
然后left指向的指针右移
(2)如果 left[0] > right [0] , list 就 append 小的数 right[0]
然后right指向的指针右移
4.终止条件:全部都比较完毕,
左边和右边指针所指下标都大于等于 left 或者right 长度
即 while left_point<len(left) and right_point<len(right)
5.终止条件的遗漏处理
终止条件会导致list append的数据丢失一个,所以需要处理
list=list+left[left_point:] # 将left指针右侧剩下的数据追加上来
list=list+right[right_point:] # 将right指针右侧剩下的数据追加上来
注意:如果为空,追加的也是[] 空列表,不会报错
程序实现流程梳理:
def merge_sort(a):
# 拆分实现
n = len(a)
# 拆分终止条件: 拆成的长度等于1
if n <= 1:
print("不执行")
return a
print("哈哈哈")
mid = n // 2
print("此时mid为:",mid)
# 拆分和合并生成的数组是对应的,可以视为merge_sort()后返回的结果是对应的 同样大小的有序数组,
left_list = merge_sort(a[:mid])
right_list = merge_sort(a[mid:])
print("左边序列left_list是:",left_list)
print("右边序列right_list是:", right_list)
打印结果:
哈哈哈
此时mid为: 2
哈哈哈
此时mid为: 1
不执行
不执行
左边序列left_list是: [2]
右边序列right_list是: [1]
此时:left_list[left],right_list[right]是: 2 1
跳出循环后,list为: [1]
哈哈哈
此时mid为: 1
不执行
不执行
左边序列left_list是: [5]
右边序列right_list是: [4]
此时:left_list[left],right_list[right]是: 5 4
我们可以看到,输入:a = [2,1,5,4]
拿到数组a 后,先判断是不是只有一个元素,
(1)输入的数组不是一个元素
执行mid = n // 2
然后继续 回归,进行拆分
left_list = merge_sort(a[:mid])
right_list = merge_sort(a[mid:])
直到拆分成数组里只有一个一个元素,即left_list是: [2] 时,进入
if n <= 1:
print(“不执行”)
return a
返回单个元素
(2)拆分完毕后,执行 上面的合并比较具体实现
即:
左边拆分,成单个元素,比较,合并
右边拆分,成单个元素,比较,合并
时间复杂度:
最优和最差都是 O(nlogn)
具体实现:
def merge_sort(a):
# 拆分实现
n = len(a)
# 拆分终止条件: 拆成的长度等于1
if n <= 1:
return a
mid = n // 2
# 拆分和合并生成的数组是对应的,可以视为merge_sort()后返回的结果是对应的 同样大小的有序数组,
left_list = merge_sort(a[:mid])
right_list = merge_sort(a[mid:])
# 将左右的数组列表进行合并
list = []
left=0
right = 0
while left<len(left_list) and right<len(right_list):
if left_list[left] < right_list[right]:
list.append(left_list[left])
left += 1
else:
list.append(right_list[right])
right += 1
list=list+left_list[left:]
list = list + right_list[right:]
return list
if __name__ == "__main__":
a = [2, 1, 8, 7, 9, 5]
print(a)
x=merge_sort(a)
print(x)
输出结果为:
[2, 1, 8, 7, 9, 5]
[1, 2, 5, 7, 8, 9]