这篇博客是对极客时间上王争课程 —— 数据结构与算法之美的个人学习总结。文章中的图出自课程中。我会对课程中的 Java 代码用 Python 来实现,所有的代码会放在我的 GitHub 上。
4. 归并排序(Merge Sort)
归并排序使用递推的方式来实现,把需要排序的数组逐步分成更小的部分,进行排序,然后再组合起来。由于是递推,最重要的是要建立递推公式:
看这里的递推公式:
递推公式
merge_sort(p...r) = merge(merge_sort(p...q), merge_sort(q+1...r))
终止条件
p >= r 不用再继续分解
递推如果看代码去理解的话会很复杂,但是建立了递推公式,按照公式来进行就会变得简单很多。这个公式就是把数组分为 p 到 q,q+1 到 r 两部分,对每一部分都进行同样的操作,直到不能再分。
按照递推公式来弄成代码就是:
# Copyright(c) strongnine
## 归并排序算法, A 是数组
def merge_sort(A):
n = len(A)
return merge_sort_c(A, 0, n - 1)
def merge_sort_c(A, p, r):
## 递归终止条件
if p >= r:
return
## 取 p 到 r 之间的中间位置 q
q = (p + r) // 2
## 分治递归
merge_sort_c(A, p, q)
merge_sort_c(A, q+1, r)
## 将 A[p...q] 和 A[q+1...r] 合并为 A[p...r]
A = merge(A, p, q, r)
return A
def merge(A, p, q, r):
i = p
j = q + 1
tmp = []
while (i <= q) & (j <= r):
if A[i] <= A[j]:
tmp.append(A[i])
i += 1
else:
tmp.append(A[j])
j += 1
## 判断哪个子数组中有剩余的数据
start = i
end = q
if j <= r:
start = j
end = r
## 将剩余的数据拷贝到临时数据 tmp
while start <= end:
tmp.append(A[start])
start += 1
return tmp
if __name__ == '__main__':
A = [1, 5, 6, 2, 3, 4]
B = [1, 2, 3, 5, 7, 8, 9, 11]
A = merge_sort(A)
B = merge_sort(B)
print(A, B)
其中最重要的就是 merge_sort_c() 这个函数,它有个嵌套。
归并排序的过程分解如下:
归并排序是非原地的稳定的算法,时间复杂度 O(nlogn),空间复杂度 O(n)。
5. 快速排序(Quicksort)
快速排序简称快排,也是用的分治思想。递推公式:
递推公式:
quick_sort(p...r) = quick_sort(p...q-1) + quick_sort(q+1, r)
终止条件:
p >= r
代码:
# Copyright(c) strongnine
## 快速排序
def quick_sort(A):
n = len(A)
quick_sort_c(A, 0, n - 1)
return A
def quick_sort_c(A, p, r):
if p >= r:
return
## 获取分区点
q = partition(A, p, r)
quick_sort_c(A, p, q - 1)
quick_sort_c(A, q + 1, r)
return A
def partition(A, p, r):
pivot = A[r]
i = p
for j in range(p, r):
if A[j] < pivot:
A[i], A[j] = A[j], A[i]
i += 1
A[i], A[r] = A[r], A[i]
return i
if __name__ == '__main__':
A = [11, 8, 3, 9, 7, 1, 2, 5]
A = quick_sort(A)
print(A)