列表每两个相邻的数,如果前边的比后边的大,那么交换这两个数
def bubble_sort(li):
for i in range(len(li) - 1):
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:
break
一趟遍历记录下最小的数,放在第一个位置:
接遍历剩余列表,继续放置:
# 如何查找最小值
def min_pos():
min_pos = 0
for i in range(1,len(li)):
if li[i] < li[min_pos]:
min_pos = i
return min_pos
# 选择排序
def select_sort(li):
for i in range(len(li) - 1):
min_pos = i
# 查找最小值
for j in range(i+1,len(li)):
if li[j] < li[mis_pos]:
min_pos = j
li[i], li[min_pos] = li[min_pos], li[i]
列表被分为有序区和无序区两个部分。最初有序区只有一个元素。
每次从无序区选择一个元素,插入有序区的位置,直到无序区变空。
def insert_sort(li):
for i in range(1,len(li)):
tmp = li[i]
j = i - 1
while j >= 0 and li[j] > tmp:
li[j+1] = li[j]
j -= 1
li[j+1] = tmp
什么是快速排序?
def qiuck_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
qiuck_sort(li, left, mid-1)
qiuck_sort(li, mid+1, left)
def patition(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
reutrn left
第二种
def quick_sort2(li):
return _quick_sort2(li)
def _quick_sort2(li):
if len(li) < 2:
return li
tmp = li[0]
left = [v for v in li[1:] if v <= tmp]
right = [v for v in li[1:] if > tmp]
left = _quick_sort2(left)
right = _quick_sort2(right)
return left + [tmp] + right
效率问题:
快排最坏是 O(N^2)
完全二叉树
时间复杂度:O(nlogn)
# 构造堆(大根堆)
def sift(li, low, high):
# li表示树,low表示树根,high表示树最后一个节点
tmp = li[low]
i = low
j = 2 * i + 1 # 初始 j 指向空位得左孩子
# i 指向空位,j 指向两个孩子
while j <= high:
if j + 1 <= high and li[j] < li[j+1]:
# 如果右孩子存在并且比左孩子大,指向右孩子
j += 1
if li[j] > tmp:
li[i] = li[j]
i = j
j = 2 * i + 1
else:
# 循环退出得第一种清空:j 位置得值比 tmp 小,说明两个孩子都比 tmp 小
break
li[i] = tmp
# 堆排序
def heap_sort(li):
n = len(li)
# 1.构造堆
for low in range(n // 2 - 1, -1, -1):
sift(li, low, n-1)
# 2.挨个出数
for high in range(n - 1, -1, -1):
li[0], lin[high] = li[high], li[0] # 退休棋子
sift(li, 0, high - 1)
python 内置模块 ——— heapq
利用模块实现堆排序
import heapq
li = [9,5,3,4,7,8,1,4]
heapq.heapify(li)
# 构建出来得是小根堆
print(li)
# heapq.heapqpush(heap, item)
heapq.heappush(li, 0)
# 往堆加元素,自动调整堆得顺序
# 获取 heapq 的最小值
item = heapq.heappop(li)
print(item)
# 最大5个数
heapq.nlargest(5, li)
# 最小5个数
heapq.nsmallest(5, li)
# 利用 heapq 模块实现堆排序
def heapsort(li):
h = []
for value in li:
heappush(h, value)
return [heappop(h) for i in range(len(h))]
拓展问题—— topK问题
现在有 n 个数,设计算法找出前 k 大的数(k 解决方法: 假设现在的列表分成两段有序,如何将其合成一个有序序列 两两比较,排序 时间复杂度:O(nlogn) 空间复杂度:O(n) 两个有序的列表排序 三种都是O(nlogn) 一般情况下,就运行时间而言: 快速排序 < 归并排序 < 堆排序 三种排序算法的缺点: 快速排序:极端情况下排序效率低 归并排序:需要额外的内存开销 堆排序:在快的排序算法中相对较慢
归并排序
def merge(li, low, mid, high):
# 列表两段有序:[low, mid] [mid+1, high]
i = low
j = mid + 1
lis_tmp = []
while i <= mid and j <= high:
if li[i] < li[j]:
lis_tmp.append(li[i])
i += 1
else:
lis_tmp.append(li[j])
j += 1
while i <= mid:
lis_tmp.append(li[i])
i += 1
while j <= high:
lis_tmp.append(li[j])
j += 1
# lis_tmp[0:high - low+1] li[low:high+1]
for i in range(low, high + 1):
li[i] = li_tmp[i-low]
# li[low:high+1] = li_tmp
def merge_sort(li, low,high):
# 排序 li 的 low 到 high 的范围
if low < high:
mid = (low + high) // 2
merge_sort(li, low, mid)
merge_sort(li, mid+1, high)
merge(li, low, mid, high)
# 两个有序的排列
def merge2list(li1, li2):
li = []
i = 0
j = 0
while i < len(li1) and j < len(li2):
if li1[i] <= li2[j]:
li.append(li1[i])
i += 1
else:
li.append(li2[j])
j += 1
while i < len(li1):
li.append(li1[i])
i += 1
while j < len(li2):
li.append(li2[j])
j += 1
return li