冒泡排序
-
列表每两个相邻的数,如果前面比后面大(升序),则交换这两个数
-
一趟排序完成后,则无序区减少一个数,有序区增加一个数
-
进行下一趟时,对整个无序区进行排列
-
代码关键点:趟、无序区范围
def bubble_sort(li):
for i in range(len(li)-1): # 第i趟 -> n-1趟
for j in range(len(li)-i-1): # 无序范围 -> [0, n-i-1]
if li[j]>li[j+1]:
a=li[j]
li[j]=li[j+1]
li[j+1]=a
return li
- 时间复杂度 O( n 2 n^{2} n2)
缺点
当无序区已经排序好之后,冒泡排序依旧会走剩下的几趟
比如如果有序列 lst=[9,8,7,1,2,3,4,5,6]
执行代码
def bubble_sort(li):
for i in range(len(li)-1): # 第i趟
print(li)
for j in range(len(li)-i-1):
if li[j] > li[j+1]:
a=li[j]
li[j]=li[j+1]
li[j+1]=a
print(li)
lst = [9,8,7,1,2,3,4,5,6]
bubble_sort(lst)
'''
输出结果为
排序前:
[9, 8, 7, 1, 2, 3, 4, 5, 6]
排序过程:
[8, 7, 1, 2, 3, 4, 5, 6, 9]
[7, 1, 2, 3, 4, 5, 6, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
实际上排序三趟就已经排完了
'''
∴ \therefore ∴ 如果在一趟过程中没有进行交换,则后续无需进行
改进
加一个标志位 exchange
def bubble_sort(li):
for i in range(len(li)-1): # 第i趟
exchange = False
print(li)
for j in range(len(li)-i-1):
if li[j] > li[j+1]:
a = li[j]
li[j] = li[j+1]
li[j+1] = a
exchange = True
if exchange == False:
break
print(li)
lst = [9,8,7,1,2,3,4,5,6]
bubble_sort(lst)
'''
输出为
排序前:
[9, 8, 7, 1, 2, 3, 4, 5, 6]
排序过程:
[8, 7, 1, 2, 3, 4, 5, 6, 9]
[7, 1, 2, 3, 4, 5, 6, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
'''
选择排序
先从列表中遍历一遍是否可以找到一个最小的数,并拿出来,再在剩下的元素中遍历······
def select_sort(li):
li_new=[]
for i in range(len(li)): # 需要遍历n遍
min_val = min(li)
li_new.append(min_val)
li.remove(min_val)
return li_new
lst = [1, 2, 5, 6, 7, 3, 2, 4]
print(select_sort(lst))
不推荐上述写法,因为
- 新建了一个列表,数据量大
- 复杂度高, ∵ \because ∵ remove、 min都不是 O ( 1 ) O(1) O(1)的操作
优化
找到最小的数和第一个数交换
def select_sort(li):
for i in range(len(li)-1):
min_loc = i
for j in range(i+1, len(li)): # 无序区范围
if li[j] < li[min_loc]:
min_loc = j
a = li[i]
li[i] = li[min_loc]
li[min_loc] = a # li[i] li[min_loc]做交换
return li
lst = [1, 2, 5, 6, 7, 3, 2, 4]
print(select_sort(lst))
插入排序
类似于打牌前理牌
从无序区抽牌插到有序区
- 要摸多少次排——n-1
- 每次摸一张
- 比较大小,决定是否挪牌
def insert_sort(li):
for i in range(1, len(li)): # i表示摸到的牌的下标
j = i-1 # j指的是手里的最后一张牌
while li[j] > li[j+1]:
a = li[j]
li[j] = li[j+1]
li[j+1] = a # 交换两位
j = j-1
if j == -1:
break
print(li)
lst = [1, 2, 5, 6, 7, 3, 2, 4]
insert_sort(lst)
时间复杂度 O ( n 2 ) O(n^{2}) O(n2)