- 冒泡排序
def bubble_sort(alist):
n = len(alist)
for i in range(0, n-1):
for j in range(i+1, n):
if alist[j] < alist[i]:
alist[i], alist[j] = alist[j], alist[i]
return alist
上述程序是从小到大排序。可以简单理解为,对于一个list来说,i是左边那个数的下标,j是右面那个数的下标。对于冒泡排序,就是用i右边的所有数(j)跟i对应的这个数进行比较。假如是从小到大排序,那么当后面那个数(j)比i对应的数小时,两个数交换,重复进行直到最后一个数。然后i+1,执行下一组循环。
- 选择排序
def select_sort(arr):
n = len(arr)
for j in range(0, n-1):
min_index = j
for i in range(j+1, n):
if arr[i] < arr[min_index]:
min_index = i
arr[min_index], arr[j] = arr[j], arr[min_index]
return arr
上述程序是从小到大排序。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。举例来说,以列表中第0索引值对应的数为最小值为例(arr[0]最小,min_index=0),将从1到最后索引值对应的数与arr[0]比较,若比arr[0]小,将当前索引值记为最小值对应的索引值(改变min_index),并继续比较。该层循环结束后将arr[0]与arr[min_index]交换,此时第0索引值对应的数为当前List中最小的数,再将列表中第1索引值对应的数做为最小值(arr[1]最小,min_index=1),以此类推。
- 插入排序
'''
插入排序可以考虑为打扑克牌时的排序
'''
def insert_sort(li):
n=len(li) #待排序的数组长度
for i in range(1, n): #从排序数组中的第二个数开始执行
tmp = li[i] # 选择一张牌
j=i-1 #这张牌前面一个的下标
while j>=0 and li[j]>tmp: # 牌前面的数是否否比较完 and 牌前面的数比这张牌大情况下才移动
li[j+1]=li[j] # 牌前面的数依次向后移动
j-=1 # 往前找一张牌
li[j+1]=tmp # 牌前面的都遍历完了或者到达停止条件,将牌放置在对应位置上
return li
插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
- 快速排序(重要)
def quick_sort(li, left, right):
if left < right:
mid = middle_choose(li,left,right)
self.quick_sort(li, left, mid-1)
self.quick_sort(li, mid+1, right)
return li
def middle_choose(li,left,right):
tmp = li[left]
while left<right:
while left<right and tmp<=li[right]:
right-=1
li[left]=li[right]
while left<right and tmp>=li[left]:
left+=1
li[right]=li[left]
li[left]=tmp
return left
快速排序的基本思想是首先将序列的第一个数找到其在序列中的对应位置,即左边的数都比这个数小,右边的数都比这个数大。再对该数左边和右边分别执行相同操作(递归思想)。
- 归并排序
def merge(lst,low,mid,high):
li1=lst[low:mid+1] # low~mid
li2=lst[mid+1:high+1] # mid+1~high
n1=len(li1)
n2=len(li2)
i, j=0, 0
li=[]
while i<n1 and j<n2:
while i<n1 and j<n2 and li1[i]>li2[j]:
li.append(li2[j])
j+=1
while i<n1 and j<n2 and li1[i]<li2[j]:
li.append(li1[i])
i+=1
while i<n1:
li.append(li1[i])
i+=1
while j<n2:
li.append(li2[j])
j+=1
for k in range(low, high+1):
lst[k]=li[k-low]
def merge_sort(li,start,end):
if start<end:
mid=(start+end)//2
merge_sort(li,start,mid)
merge_sort(li,mid+1,end)
merge(li,start,mid,end)
归并排序的思想主要是从两个有序序列合并成一个有序序列而来(上面的merge()函数)。所以归并排序主要分为两个步骤,第一步是将给定序列递归二分,再将二分后的序列递归合并成一个有序序列。整个过程比较复杂,主要采用递归的思想。
上述五种排序是比较基本的排序方法,面试也经常会考到手撕代码,建议熟练掌握。附上上述五种排序的时间复杂度及稳定性: