更新中 ...
稳定性:排完序后,所有等值元素的相对位置保持不变
适应性:排序算法对顺序不同的待排序序列,表现出差异性(越有序,越高效)
1 插入排序(稳定性,适应性)
平均时间复杂度O(n^2),最好O(1)
原地排序,空间复杂度为O(1)
原理:从序列最左侧开始遍历,用该元素首先比较其相邻的左侧元素(左侧已排好),若该元素比其小,则左侧元素右移,继续比较该元素和左侧第二个的大小(注意,比较的是该元素temp和list[j-1],非list[j]和list[j-1])...直至找到正确位置。
def insert(lst):
for i in range(1,len(lst)):
temp=lst[i]
j=i
while j>0 and lst[j-1]>temp:
lst[j]=lst[j-1]
j-=1
lst[j]=temp
return lst
2 冒泡(稳定性,适应性)
平均时间复杂度O(n^2),最好O(1)
原地排序,空间复杂度为O(1)
原理:通过交换元素消除逆序实现排序。发现相邻的逆序对就进行交换,通过反复比较和交换完成排序。(每次都能保证把最大元素移到未排序部分的最后,所以每次未排序部分都减少一位 j in range(1,len(lst) - i ))
def bubble(lst):
for i in range(len(lst)):
for j in range(1,len(lst)-i):
if lst[j-1]>lst[j]:
lst[j],lst[j-1]=lst[j-1],lst[j]
return lst
3 简单选择(稳定性,无适应性)
平均时间复杂度O(n^2),所有情况都是O(n^2),比较总次数1+2+3+...+N-1=N *(N - 1) / 2。
原地排序,空间复杂度为O(1)
原理:每次从剩余未排序的子序列中选择出最小的,放入左侧已排序子序列的后面
def simpleselect(lst):
for i in range(len(lst)-1):
k=i
for j in range(i+1,len(lst)):
if lst[j]<lst[k]:
k=j
if k==i:continue
lst[i],lst[k]=lst[k],lst[i]
return (lst)
4 归并排序(稳定性,无适应性)
时间复杂度:O(n log n) 归并的遍数不多于:log n +1, 每次归并做得比较次数是 n
空间复杂度: O(n),需要一个与原序列长度相等的序列,然后两个交错使用进行归并
原理:将长度为n的序列,分成n个子序列,两两归并子序列(有序子序列长度加倍),重复操作得到长度为n的有序序列
def mergesort(seq):
if len(seq) <= 1:
return seq
#定义内部两两合并函数
def merge(left, right):
result = [] # 新的已排序好的列表
i = 0 # 下标
j = 0
# 对两个列表中的元素 两两对比。
# 将最小的元素,放到result中,并对当前列表下标加1
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]#将剩余的排好序的直接加入result,+=,不可用append
result += right[j:]
return result
mid = len(seq) // 2
left = mergesort(seq[:mid]) #递归
right = mergesort(seq[mid:])
return merge(left, right)
#或者将中间合并函数merge简化为:
def merge(left, right):
result = []
while left and right:
result.append(left.pop(0) if left[0]<=right[0] else right.pop(0))
if left:
result+=left
if right:
result+=right
return result
测试:
input_list = [6, 4, 8, 9, 2, 3, 1,-1]
print('排序前:', input_list)
sorted_list = mergesort(input_list)
print('排序后:', sorted_list)
result:
排序前: [6, 4, 8, 9, 2, 3, 1, -1]
排序后: [-1, 1, 2, 3, 4, 6, 8, 9]
5 快排(无稳定性,无适应性)
时间复杂度:最好O(nlogn),最坏O(n^2)
空间复杂度:O(logn)
原理:每次选择一个基准元素,两个指针从头和尾分别遍历,先从尾开始遍历,一直找到小于base的,然后复值给头,然后头指针向后遍历,找到大于base的,赋值给尾指针。最后将base赋值给头指针,然后递归处理左右两边子数组。
def quick_sort(s,l,r):
if l>=r: return
i=l
j=r
base=s[i]
while i<j:
while i<j and s[j]>=base: #右边开始找小于base的元素
j-=1
s[i]=s[j]
while i<j and s[i]<=base: #左边开始找大于base的元素
i+=1
s[j]=s[i]
s[i]=base #最后s[i]是空的,base赋值
quick_sort(s,l,i-1) #递归处理左右两边的子数组
quick_sort(s,j+1,r)
return s