归并排序
归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
如图
那么怎么把一个数列分开成最小呢?用递归的方法,代码如下
def merge_sort(alist):#alist是一个列表,元素为待排序的元素
if len(alist) <= 1:
#如果长度变为1了之后,退出递归,也有可能小于1,因为1除以2取整就是0
return alist
# 二分分解
num = len(alist)//2
left = merge_sort(alist[:num])#用一个变量来接受递归退出后返回来的列表
right = merge_sort(alist[num:])
拆分了之后,如何合并呢?先来看一个例子
1,5是一组 3,4 是一组
如何将这两组合并为一组,且合成的的组里面的元素是有序排列
首先是1 和 3 比较,1 小,放到一个新的列表中,这时需要定义一个空的列表result = [].
把1加进空的列表中,这时result = [1];
这步完成之后,再将5和3比较,3小,加进列表中,此时result = [1,3];
此时再拿4和5比较,4小,加进去,此时result = [1,3,4]
最后剩下5,同样放进去。此时result = [1,3,4,5]。到此,就合并完成了。具体实现代码如下
left_point, right_point = 0, 0
result = []
while left_point < len(left) and right_point < len(right):
#这里的left = [1,5],right = [3,4]
if left[left_point] > right[right_point]:
result.append(right[right_point])
right_point += 1
else:
result.append(left[left_point])
left_point += 1
result += right[right_point:]
result += left[left_point:]#这行的意思按照我上面说的例子就是将5添加进来
总体的实现代码如下
#coding: utf-8
'''归并排序'''
def merge_sort(alist):
if len(alist) <= 1:
return alist
# 二分分解
num = len(alist)//2
left = merge_sort(alist[:num])
right = merge_sort(alist[num:])
left_point, right_point = 0, 0
result = []
while left_point < len(left) and right_point < len(right):
if left[left_point] > right[right_point]:
result.append(right[right_point])
right_point += 1
else:
result.append(left[left_point])
left_point += 1
result += right[right_point:]
result += left[left_point:]
return result
def main():
# li = [54,78,36,36,79,68,0,2,9,1]
# li = [1,2,3,4,5,6,7]
# li = [9,8,7,6,5,4,3,2,1]
li = [9,1,5,3,4,2,6,8,7]
a = merge_sort(li)
print(a)
if __name__ == "__main__":
main()