【python & 归并排序算法】
算法基本原理思想
- 归并排序体现分而治之的分治策略
-归并排序是递归算法,思路是将数据表持续分裂为两半,对两半分别进行归并排序
- 递归的基本结束条件是:数据表仅有1个数据项,自然是排好序的;
- 缩小规模:将数据表分裂为相等的两半,规模减为原来的二分之一;
- 调用自身:将两半分别调用自身排序,然后将分别排好序的两半进行归并,得到排好序的数据表
- 算法流程示意图:
简单排序代码示例
基本传统的代码:
'''
@ time :2021年10月22日
@ author : wupke
@ description: 归并排序算法
'''
import time
# # #
start1 = time.clock()
def mergeSort(alist):
# print("splitting",alist)
# 包含了递归的基本结束条件:代码中已经表示了,当len(list)<=1 ,就会退出程序
if len(alist)>1:
mid = len(alist)//2
lefthalf = alist[:mid]
righthalf = alist[mid:]
# 递归调用
mergeSort(lefthalf)
mergeSort(righthalf)
# 拉链式交错把左右半部分从小到大顺序归并到结果列表中
i = j = k =0
while i<len(lefthalf) and j < len(righthalf):
if lefthalf[i]<righthalf[j]:
alist[k]=alist[i]
i = i+1
else:
alist[k]=righthalf[j]
j = j+1
k = k+1
#归并左半部分剩余项
while i<len(lefthalf):
alist[k] = lefthalf[i]
i=i+1
k=k+1
#归并右半部分剩余项
while j<len(righthalf):
alist[k] = righthalf[j]
j=j+1
k=k+1
alist = [22,33,44,55,21,31,45,76,88,54,3,5,7,2]
mergeSort(alist)
end1 = time.clock()
print("%s排序用时%s" %(alist,(end1-start1)))
- 算法流程图:
python 化的代码版本:
- 代码
'''
@ time :2021年10月22日
@ author : wupke
@ description: 归并排序算法
'''
import time
# # #
start1 = time.clock()
def merge_Sort(lst):
# 递归基本结束条件
if len(lst) <=1:
return lst
# 问题分解 并递归调用
middle = len(lst)//2
# 左半部分排好序
left = merge_Sort(lst[:middle])
# 右半部分排好序
right = merge_Sort(lst[middle:])
# 合并左右部分 ,完成排序
merged = []
while left and right:
if left[0] <= right[0]:
merged.append(left.pop(0))
else:
merged.append(right.pop(0))
#归并左右余项
merged.extend(right if right else left)
return merged
alist = [22,33,44,55,21,31,45,76,88,54,3,5,7,2]
merge_Sort(alist)
end1 = time.clock()
print("%s排序用时%s" %(alist,(end1-start1)))
复杂度分析
- 将归并排序分为两个过程来分析:分裂和归并
- 分裂的过程,借鉴二分查找中的分析结果,是对数复杂度,时间复杂度为O(log n)
- 归并的过程,相对于分裂的每个部分,其所有数据项都会被比较和放置一次,所以是线性复杂度,其时间复杂度是O(n)
- 综合考虑,每次分裂的部分都进行一次0(n)的数据项归并,总的时间复杂度是0(nlog n)
- 最后,我们还是注意到两个切片操作为了时间复杂度分析精确起见,可以通过取消切片操作,改为传递两个分裂部分的起始点和终止点,也是没问题的,只是算法可读性稍微牺牲一点点。
- 要注意到归并排序算法使用了额外1倍的存储空间用于归并
这个特性在对特大数据集进行排序的时候要考虑进去