算法子目录:https://blog.csdn.net/qq_41106844/article/details/105553931
归并排序流程图
归并排序思路
1.满足归并排序输入的(一个无序列表里面有两个有序列表),直接使用归并算法处理。
2.两个有序列表混合排序,将两个列表当做两个有序区,使用归并算法处理。
3.将一个无序列表排序,需要先分解再合并。
分解与合并
代码
#归并算法
def merge(li,low,mid,high):
'''
:param li:排序的列表
:param tmp:首元素
:param mid: 第一段有序末位
:param high: 尾元素
:return:
'''
i = low #tmp1
j = mid + 1 #tmp2
li_tmp = [] #有序列表
#出循环的情况是,第一个列表空了,或者第二个列表空了。
while i <= mid and j <= high:
#如果第二个列表的元素大于第一个列表的元素,就把第一个列表里的元素放到有序区,然后第一个列表索引+1
if li[i] <= li[j]:
li_tmp.append(li[i])
i += 1
else:
li_tmp.append(li[j])
j += 1
#这里是看两个列表,如果有一个空了,另一个还有没有元素,有的话就全放到有序区。
while i <= mid:
li_tmp.append(li[i])
i += 1
while j <= high:
li_tmp.append(li[j])
j += 1
# it_tmp[0:]=li[low:high+1]
#然后把有序区覆盖掉原来的列表,这样就不用返回列表了。
for i in range(low,high+1):
li[i] = li_tmp[i-low]
#两个有序列表
def merge_list(li1,li2):
'''
列表再多点的话,推荐reduce()函数。
:param li1:
:param li2:
:return:
'''
li = []
i = 0
j = 0
while i <len(li1) and j < len(li2):
if li[i] <= li[j]:
li.append(li1[i])
i += 1
else:
li.append(li2[j])
j += 1
while i <= len(li1):
li.append(li1[i])
i += 1
while j <= len(li2):
li.append(li2[j])
j += 1
#一个无序列表
def merge_sort(li,low,high):
'''
把一个乱序列表两个一半长度的有序列表。(让一个列表满足归并的条件)
分解与合并。
:param li:
:param low:
:param high:
:return:
'''
if low < high:
mid = (low + high) // 2
merge_sort(li,low,mid)
merge_sort(li,mid+1,high)
merge(li,low,mid,high)
总结
稳定性:归并排序是一种稳定排序。
比较性:因为排序时元素之间需要比较,所以是比较排序。
此外,归并排序中的比较次数是所有排序中最少的。原因是,它一开始是不断地划分,比较只发生在合并各个有序的列表时。
时间复杂度:T(N) = 2T(N/2) + O(N) 可知时间复杂度为O(NlogN)
列表的初始顺序会影响到排序过程中的比较次数,但是总的而言,对复杂度没有影响。平均情况 or 最坏情况下 它的复杂度都是O(NlogN)
空间复杂度:归并排序中,用到了一个临时列表,故空间复杂度为O(N)