归并排序
归并排序说的简单一点就是把一个大的序列分成多个子序列,再别对各个子序列进行排序,等所有子序列都排序完成之后,再逐步从所有的子序列里面抽出最小的元素放回到大序列里面。直至所有元素都放回大序列,从而完成排序。
是采用分治法的典型案例。
本例是 二路归并。
一个大的序列
分成两个子序列分别进行排序
如图所示,最终将两个排好序的子序列,合并成一个,完成排序。
一种是递归的方式:
该方法是递归的将序列分成两个部分,直至每个部分都只有一个元素,然后在返回,逐个的将相邻部分,排序、合并从而实现总的排序。
代码如下:
def merge(left, right): """合并左右两个子序列""" merged = [] # 设置一个空序列用以盛放每次从子序列中拿出的小的元素 i, j = 0, 0 #初始化 i j 两个游标,分别跟踪 左右两个子序列的最小元素,因为左右两个序列已经从小到大排序好了,所以i j 均为 0 left_len, right_len = len(left), len(right) while i < left_len and j < right_len: # i j 作为左右子序列的游标,他们是不能超过两个子序列的长度的。一旦超过,说明该子序列遍历完成 if left[i] <= right[j]: #分别比较两个子序列中最小的那个。即 i j分别指向的那两个元素 merged.append(left[i]) #小的加入到 临时序列,同时 游标向右移动 i += 1 else: merged.append(right[j]) j += 1 merged.extend(left[i:]) #当上个循环退出的时候,说明其中一个子序列已经遍历完成,于是将另一个子序列的剩余所有元素放入到临时序列中 merged.extend(right[j:]) #此中情况是 i 坐在的左序列提前遍历完了,于是右子序列的从j开始的所有剩余元素都放到临时序列中 return merged #返回临时序列 def merge_sort(lst): if len(lst) <= 1: #如果序列的长度为 1 了,那么就返回该序列 return lst middle = len(lst) // 2 left = merge_sort(lst[:middle]) #递归的对序列的左半部分进行分解 right = merge_sort(lst[middle:]) #递归的对序列的右半部分进行分解 return merge(left, right) #合并左右两个子序列。 a = [1,4,7,3,5,89,64,32,46] print(merge_sort(a))