-
插入排序:
其排序时间复杂度为,它在待排列表中较低的一端维护一个有序的子列表,并逐个将每个新元素‘插入’这个子列表中。
nums = [54,26,93,17,77,31,44,55,20]
for i in range(1,len(nums)):
currentvalue = nums[i]
position = i
while position>0 and currentvalue<nums[position-1]:
nums[position] = nums[position-1]
nums[position-1] = currentvalue
position -=1
nums[position] = currentvalue
print(nums)
结果:
[17, 20, 26, 31, 44, 54, 55, 77, 93]
在最坏的情况下,插入排序算法的比较是前n-1个整数之和(1+2+3+...+n-1),对应的复杂度为
在最好的情况下(列表已经有序),每一论只比较一次(1+1+1.....),对应的复杂度为。
所以,当插入一个新元素,且原有列表已经有序的情况下,插入排序很有效率。
-
希尔排序:
希尔排序也称"递减增量排序",它对插入排序做了改进,将列表分成数个子列表,并对每一个子列表应用插入排序。如何切分列表是希尔排序的关键(并不是连续切分,而是使用增量i(有时称作为步长),选取所有间隔为i的元素组成子列表)
def gapinsertionsort(alist, start, gap):
for j in range(start+gap,len(alist),gap):#以最小元素为为最小端进行插入排序
position = j
currentvalue = alist[position]
while position > start and alist[position] < alist[position-gap]:
alist[position] = alist[position-gap]
alist[position-gap] = currentvalue
position -=gap
alist[position] = currentvalue
nums = [54,26,93,17,77,31,44,55,20]
iter = len(nums)//2 #第一次分成iter个子列表
while iter > 0:
for startposion in range(iter):
gapinsertionsort(nums , startposion, iter)#对每个子列表进行插入排序
iter //=2 重复划分子列表,直到子列表为1
print(nums)
结果:
[17, 20, 26, 31, 44, 54, 55, 77, 93]
希尔排序每一次都是对子列表进行了一次插入排序,也就是说每一轮的遍历都生成了"更有序"列表。它的最大复杂度为
-
归并排序
归并排序采用的是分治策略。它是一种递归算法,每次将一个列表一分为二。如果列表为空或者只有一个元素,那么它就变得有序了。当两个部分都有序时,就进行归并(将两个较小的有序列表归并为一个有序列表的过程)这一基本操作。如图1所示:
该图截选于<<大话数据结构>>
递归版本:
def mergesort(alist,L,R):
print('spliting', alist[L:R + 1])#打印每一次递归切分的子列表
if L<R:#设置一个递归结束的条件
mid=L+((R-L)>>1)#获取子列表中的中键
mergesort(alist,L,mid)#对左部分排序
mergesort(alist,mid+1,R)#对右部分排序
merge(alist,L,mid,R)#将有序的两个子列表合并在一起
def merge(alist,L,mid,R):
r=mid+1
l=L
temp=[]
while l<=mid and r<=R:#先对两个子列表进行比对,把小指添加到temp数组,其中必有一个子列表被遍历完
if alist[l]<alist[r]:
temp.append(alist[l])
l+=1
else:
temp.append(alist[r])
r+=1
#判断还有哪一个子列表没有遍历完,将剩余的元素添加到temp数组中
while l<=mid:
temp.append(alist[l])
l+=1
while r<=R:
temp.append(alist[r])
r+=1
#将temp数组中的值,赋给原素组中去
alist[L:R+1]=temp
print("merging",alist[L:R+1])#打印递归以后merge的过程
#获取一个数组,进行排序。
nums=list(map(int,input().split()))
print(nums)
mergesort(nums,0,len(nums)-1)
print(nums)
整个结果图也是整个递归以及merge的过程图,应该来说是便于理解的。spliting表示二分列表的过程,merging表示合并两个子列表的过程
复杂度分析:由图一所示,当列表的长度为n时,能切分次,每一次需要进行n次操作,所以,时间复杂度为