1、 定义
先拆分再合并
- 拆分时按照先对半,再将分出的子序列对半,以此类推,直到分为单个的元素
- 合并时,合并的两个组来自原来拆分之前的组,先两两合并,合并的同时,将这两个元素排序
- 再将合并后的序列们两两合并,合并时有两个游标,left、right,left指向左边序列的第一个元素,right指向右边序列的第一个元素,
- 首先比较这两个元素的大小,如果左边小于右边,则将左边的元素放到合并的序列中的第一位,向右移动left一位,
- 如果右边的更小,则将右边的元素放在合并的序列中的第一位,right游标向右移一位,继续比较两个游标所指的元素的大小;
- 同样的方法将剩下的序列两两合并
- 以此类推,直至最后合并为一个序列
2、python实现
先会分为两个,然后先处理左侧的子序列,将左侧的子序列排好序,再处理右侧的子序列;
在处理左侧的子序列时,再调用merge函数,将它分为两个子序列,然后再先处理左侧序列;
直到不可再分时,向下执行合并;
先合并为两个,然后合并右侧的;
然后合并为四个,先左侧再右侧;
左边的都排好后,再排右侧,与左侧的步骤相同
def merge_sort(alist):
# 先拆分
n=len(alist)
mid=n//2
if n <= 1:
# mid为序列中间元素的索引,如果这个索引小于等于1 ,则表示此时已经拆分为单个元素的序列
# 不做操作返回
return alist
# left、right表示采用归并排序后有序的新的序列
left_li=merge_sort(alist[:mid]) #或list[:mid]
right_li=merge_sort(alist[mid:]) # 或list[mid:]
# 将两个有序的子序列合并为一个新的整体
# merge(left,right)
# 左右两个游标都从0索引开始
left_pointer,right_pointer=0,0
result=[]
while left_pointer<len(left_li) and right_pointer < len(right_li):
# 只要两个子序列的游标都没越界就一直执行
if left_li[left_pointer] <= right_li[right_pointer]:
result.append(left_li[left_pointer])
left_pointer += 1
else:
result.append(right_li[right_pointer])
right_pointer += 1
# 当退出循环时,子序列一般还剩一个元素,将最后的这个元素加入result中
result += left_li[left_pointer:]
result += right_li[right_pointer:]
return result
if __name__ == '__main__':
list=[11,43,2,4,55,78,45,97,56,73,38]
print(list)
new_list=merge_sort(list)
print(new_list)
结果:
[11, 43, 2, 4, 55, 78, 45, 97, 56, 73, 38]
[2, 4, 11, 38, 43, 45, 55, 56, 73, 78, 97]
3、时间复杂度
- 最优时间复杂度:O(nlogn)
- 最坏时间复杂度;O(nlogn)
- 稳定性:稳定(只要在判断大小时,将小于改为小于等于,可以保证在等于的时候将左侧的值先放入序列)