defbubble_sort(li):for i inrange(len(li)-1):
exchange =Falsefor j inrange(len(li)-i-1):if li[j]> li[j+1]:
li[j], li[j+1]= li[j+1], li[j]
exchange =Trueifnot exchange:return li
# 测试样例import random
li =[i for i inrange(10)]
random.shuffle(li)print(li)
bubble_sort(li)print(li)'''result
[7, 5, 1, 6, 9, 0, 2, 3, 8, 4]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
'''
二、选择排序
从列表中选择一个最小的,放到新的列表,该过程循环n次
# 非原地排序,需重新开辟新数组defselect_sort_simple(li):
li_new =[]for i inrange(len(li)):for val in li:
min_val =min(li)
li_new.append(min_val)
li.remove(min_val)return li_new
对上述方法优化,采用原地排序,因此遍历 n-1 次即可
一趟排序记录最小的数,放到第一个位置
在一趟排序记录无序区最小的数,放到第二个位置, …
关键点:有序区、无序区、无序区最小数的位置
defselect_sort(li):for i inrange(len(li)-1):
min_col = i
for j inrange(i+1,len(i):if li[j]< li[min_col]:
min_col = j
li[i], li[min_col]= li[min_col], li[i]return li
三、插入排序
初始时手里(有序区)只有一张牌
每次(从无序区)摸一张牌,插入到手里已有手牌的正确位置
definsert_sort(li):for i inrange(1,len(i)):
tmp = li[i]
j = i -1while li[j]> tmp and j >=0:
li[j+1]= li[j]
j -=1
li[j+1]= tmp
return li
四、快速排序
defpartition(li, left, right):
tmp = li[left]while left < right:while left < right and li[right]>= tmp:
right -=1
li[left]= li[right]while left < right and li[left]<= tmp:
left +=1
li[right]= li[left]
li[left]= tmp
return left
defquick_sort(li, left, right):if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid-1)
quick_sort(li, mid+1, right)
五、堆排序
建立堆(最大堆)
得到堆顶元素,为最大元素
去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序
堆顶元素为第二大元素
重复步骤3,直至堆变空
从父亲找孩子:i = low,j = 2*i+1
从孩子找父亲:j = high,i = (j-1) // 2
defsift(li, low, high):
i = low
j =2*i+1
tmp = li[low]while j <= high:if j+1<= high and li[j+1]> li[j]:
j = j+1if li[j]> tmp:
li[i]= li[j]
i = j
j =2*i+1else:break
li[i]= tmp
defheap_sort(li):
n =len(li)for i inrange((n-2)//2,-1.-1):
sift(li, i, n-1)for i inrange(n-1,-1,-1):
li[0], li[i]= li[i], li[0]
sift(li,0, i-1)
使用内置模块heapq实现堆排序
常用函数:
heapify(x): 建最小堆
heappush(heap, item)
heappop(heap): 每次弹出最小元素
import heapq
import random
li =list(range(10))
random.shuffle(li)print('无序列表', li)
heapq.heapify(li)# 建堆
new_li =[]for i inrange(len(li)):
min_value = heapq.heappop(li)# 每次弹出最小元素
new_li.append(min_val)
definsert_sort_gap(li, gap):for i inrange(gap,len(li)):
tmp = li[i]
j = i -gap
while j >=0and li[j]> tmp:
li[j+gap]= li[j]
j -= gap
li[j+gap]= tmp
defshell_sort(li):
d =len(li)//2while d >=1:
insert_sort_gap(li, d)
d //=2
八、计数排序
对列表进行排序,已知列表中的数范围都在0-100之间,设计复杂度为O(n)的算法。
defcount_sort(li, max_count=100):
count =[0for _ inrange(max_count+1)]for val in li:
count[val]+=1
li.clear()for ind, val inenumerate(count):for i inrange(val):
li.append(ind)
九、桶排序
桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。
平均情况时间复杂度: O(n+k)
最坏情况时间复杂度: O(n2k)
空间复杂度:O(nk)
defbucket_sort(li, n=5, max_num=10):
buckets =[[]for _ inrange(n)]for var in li:
i =min(var//(max_num//n), n-1)
buckets[i].append(var)for j inrange(len(buckets[i])-1,0,-1):if buckets[i][j]< buckets[i][j-1]:
buckets[i][j], buckets[i][j-1]= buckets[i][j-1], buckets[i][j]else:break
sorted_li =[]for buc in buckets:
sorted_li.extend(buc)return sorted_li
十、基数排序
多关键字排序
时间复杂度:O(kn)
空间复杂度:O(k+n)
k表示数字位数
defradix_sort(li):
max_num =max(li)
it =0while it**10<= max_num:
buckets =[[]for i inrange(10)]for var in li:
digit =(var//10**it)%10
buckets[digit].append(var)
li.clear()for buc in buckets:
li.extend(buc)
it +=1