排序
- 意思:将一组“无序”的记录序列调整为“有序”的记录序列
- 列表排序:将无需列表变为有序列表
- 输入:列表
- 输出:有序列表
- 升序与降序
- 内置排序函数:sort()
常见排序算法
- 普通:冒泡排序、选择排序、插入排序...
- 进阶:快速排序、堆排序、归并排序...
- 其他:希尔排序、计数排序、基数排序...
冒泡排序(Bubble Sort)
- 列表每两个相邻的数,如果前面比后面大,则交换这两个数
- 一趟排序完成后,无序区减少一个数,有序区增加一个数
- 排完需要n-1趟
- 算法关键点:趟、无序区范围
- 时间复杂度O(n^2)
代码:
def bubble_sort(li):
for i in range(len(li)-1): #第i趟
for j in range(len(li)-i-1): #指针范围
if li[j] > li[j+1]: #此处升序,降序改为<
li[j], li[j+1] = li[j+1], li[j]
改进:如果当前趟排序完后与上一趟的排序结果相同,说明已经排序完毕,不需要跑完全部n-1趟
def bubble_sort(li):
for i in range(len(li)-1): #第i趟
exchange = False
for j in range(len(li)-i-1): #指针范围
if li[j] > li[j+1]: #此处升序,降序改为<
li[j], li[j+1] = li[j+1], li[j]
exchange = True
if not exchange:
return
快速排序(Select Sort)
- 意思:一趟排序记录最小的数,放到第一个位置,再一趟排序,无序区最小的数放到第二个位置......
- 排完需要n-1趟
- 算法关键点:有序区和无序区、无序区最小数的位置
- 时间复杂度O(n^2)
不太好的代码:
def select_sort_simple(li):
li_new = []
for i in range(len(li)):
min_val = min(li)
li_new.append(min_val)
li.remove(min_val)
return li_new
#缺点是新列表占内存,min、remove都是O(n),所以最后的时间复杂度是O(n^2)
正常代码:
def select_sort(li):
for i in range(len(li)-1): #第i趟
min_loc = i
for j in range(i+1, len(li)): #无序区范围
if li[j] < li[min_loc]:
min_loc = j
li[i], li[min_loc] = li[min_loc], li[i]
插入排序(Insert Sort)
- 初始时手里(有序区)只有一张牌
- 每次(从无序区)摸一张牌,插入到手里已有牌的正确位置
- 时间复杂度O(n^2)
def insert_sort(li):
for i in range(1, len(li)): #表示摸到的牌的下标
temp = li[i] #摸到的牌的值
j = i-1 #手里的牌的下标
while j >= 0 and li[j] > temp:
li[j+1] = li[j]
j -= 1
li[j+1] = temp
冒泡、选择、插入的共同点
- 都是原地排序
- 时间复杂度都是O(n^2)