学习Python的过程中,用Python实现了一下常用的排序算法。其实按照目前的工作感受老说,也不能说常用吧,只能说常见,很多都是大学算法考完之后的久别重逢。
冒泡排序
时间复杂度O(n²) 稳定1
2
3
4
5
6
7def bubble_sort(L):
for x in range(len(L)-1): ##每次最大元素沉到最下面,len(L)-1 次
for y in range(len(L)-1-x): ##相邻元素比较。次数减去已完成下沉的x个元素
if L[y]>L[y+1]:
L[y],L[y+1]=L[y+1],L[y]
#print(x,":",L)
return L
选择排序
时间复杂度O(n²) 不稳定1
2
3
4
5
6
7
8
9
10def selection_sort(L):
for x in range(len(L)):
min_index = x #记录最小元素的索引
for y in range(x+1,len(L)):#选择出未排序元素里面最小的
if L[y]<L[min_index]:
min_index = y
if min_index != x:
L[x],L[min_index] = L[min_index],L[x]
print(x,":",L)
return L
直接插入排序
时间复杂度O(n²) 稳定
原理:类似于摸牌,左手上是有序的,右手摸一张牌,寻找插入点插入1
2
3
4
5
6
7
8
9def insertion_sort(L):
for x in range(1,len(L)):
temp = L[x] # 未排序的第一个元素
y=x-1 # 从已排序的最后一个元素开始查找插入点
while y>=0 and L[y]>temp: # 循环条件是索引不小于0且元素大于待插入的值
L[y+1] = L[y] # 元素后移
y-=1
L[y+1] = temp # y已经是小于等于待插入值了,y+1处为插入位置
return L
二分插入排序
时间复杂度O(n²)
元素移动次数与直接插入排序相同。n较大时,比较次数比直接插入排序的最差情况好很多,比直接插入最好情况要差,所以接近升序时,直接插入排序比较好1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def insertion_dichotomy_sort(L):
for x in range(1,len(L)):
temp = L[x]
left = 0
right = x-1
while (left<right): #通过二分法查找插入的位置
middle = (left+right)//2
if L[middle]>temp:
right = middle-1
else:
left = middle+1
y = x-1
while y>=left:
L[y+1] = L[y]
y-=1
L[left] = temp
return L
希尔排序
希尔排序(递减增量排序,直接插入排序的高效版本) 时间复杂度O(nlogn)~O(n²) 不稳定
插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位
希尔排序通过设置一定的增量,这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

1 | def shell_sort(L): |
归并排序
时间复杂度O(nlogn) 辅助空间O(n) 稳定1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21def MergeSort(lists):
if len(lists) <= 1:
return lists
num = len(lists)//2
left = MergeSort(lists[:num])
right = MergeSort(lists[num:])
return Merge(left, right)
def Merge(left,right):
r, l=0, 0
result=[]
while l<len(left) and r<len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += right[r:]
result += left[l:]
#print(left,right,"==>",result)
return result
原来使用的是另一种不够Pythonic的方式,从C语言的实现中翻译来的写法,遇到了一些问题,知乎网友已协助解答。
快速排序
时间复杂度O(nlogn) 辅助空间O(logn)~O(n) 不稳定1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def quickSort(L, low, high):
i = low
j = high
if i >= j:
return L
key = L[i] #基准
while i < j:#把所有比基准值小的元素放在基准前面,所有比基准值大的元素放在基准的后面
while i < j and L[j] >= key:
j = j-1
L[i] = L[j]
while i < j and L[i] <= key:
i = i+1
L[j] = L[i]
L[i] = key
quickSort(L, low, i-1)
quickSort(L, j+1, high)
print(low,high,L)
return L
堆排序
时间复杂度O(nlogn) 不稳定
测试:1
2L=[2,5,2,6,8,1,12,3,5,0]
print(quickSort(L,0,len(L)-1))