个人总结,仅供参考。详细内容请阅读《Introduce to Algorithm》算法导论
heap sort
- 用数组存储最大堆,用二叉树表示最大堆特征结构
图1(heap与array对应关系)
-
Parent(i)
- return ⌊ i/2 ⌋ 取下等 Left(i)
- return 2i Right(i)
- return 2i+1
max-heap的特征 : A[Parent(i)]>=A[i]
method:
- maxHeapity:时间复杂程度为O(lgn), 是维护max-heap性质的关键.
- buildMaxHeap:线性时间复杂程度, 输入一个乱序的数组,最终生成最大堆.
- heapSort:时间复杂程度为O(nlgn), 对数组进行排序.
- maxHeapInsert、heapExtractMax、heapIncreaseKey、heapMaximum : 时间复杂程度为O(lgn) , 利用堆实现优先级队列.
图2(求maxHeapity)
//maxHeapity : 假设节点i的左右子树都已经是最大堆
maxHeapity(A, i ) {
l = Left(i)
r = Right(i)
largest = i
if l <= A.hipeSize && A[l] > A[i]
largest = l
if r < A.heapSize && A[r] > A[largest]
largest = r
if largest != i
exchange A[i] with A[largest] //**不稳定**
maxHeapity(a, largest)
}
图3(buidMaxHeap)
buildMaxHeap(A) {
A.heapSize = A.length
for i = A.length/2 to 1 //取下等
maxHeapity(A, i)
}
heapSort(A) {
buildMaxHeap(A)
for i = A.length dowmto 2
exchange A[1] with A[i]
A.heapSize = A.heapSize - 1
maxHeapity(A, 1)
}
- priority queue:根据排序数值的大小,确定优先级
heapMaximum(A){
return A[1]
}
heapExtractMax(A) {
if A.heapSize < 1
error "heap underflow"
max = A[1]
A[1] = A[A.heapSize]
A.heapSize = A.heapSize -1
maxHeapity(A, 1)
return max
}
heapIncreaseKey(A, i, key) {
if key < A[i]
error "new key is smaller than current key"
A[i] = key
while i > 1 and A[PARENT[i] < A[i]]
exchange A[i] with A[PARENT[i]]
i = PARENT[i]
}
maxHeapInsert(A, key) {
A.heapSize = A.heapSize + 1
A[A.heapSize] = -@
heapIncreaseKey(A, A.heapSize ,key)
}
扩展:思考如何使用FIFO队列,FILO栈实现优先级队列。
quick sort
- 思路:拆分–根据pivot把数组分为两半
图4(partition示意图)
quickSort(A, p, r) {
if p < r
q = partition(A, p, r)
quickSort(A, p, q - 1)
quickSort(A, q + 1, r)
}
partition(A, p, r) {
x = A[r]
i = p - 1
for j = p to r -1
if A[j] <= x
i = i + 1
exchange A[i] with A[j] // **不稳定**
exchange A[i + 1] with A[r]
return i + 1
}
扩展:注意我们选择的partition选取的pivot总是最后一个数,思考如何实现随机选取pivot。文章底部给出实现思路。
insert,bubble,select sort O(n2)
- bubble : 找到最大数,移到最后
- Insert :从后插入到排好序的数值
- shell : 缩小增量排序,又叫分组插入排序法,根据增量分成相应的组,再缩小增量,到1。
- select : 从待排序的数组中选出最大或最小元素,与起始位置交换 //不稳定
insertSort(A) {
for j = 2 to A.length
key = A[j]
//Insert A[j] into the sorted sequence A[1..j - 1]
i = j - 1
while i > 0 && A[i] > key
A[i + 1] = A[i]
i = i - 1
A[i + 1] = key
}
merge sort
- 思路:先拆分,再合并排好序的两个数组
mergeSort(A, p, r) {
if p < r
q = _(p + r)/2_
mergeSort(A, p , q)
mergeSort(A, p + 1, r)
merge(A, p, q, r)
}
merge(A, p, q, r) {
n1 = q - p + 1
n2 = r - q
let L[1..n1 + 1] and R[1..n2 + 1] be new array
for i = 1 to n1
L[i] = A[p + i -1]
for j = 1 to n2
R[j] = A[q + j]
L[n1 + 1] = @
R[n2 + 1] = @
i = 1
j = 1
for k = p to r
if L[i] <= R[j]
A[k] = L[i]
i = i + 1
else A[k] = R[j]
j = j + 1
}
bucket sort
适合场景:输入的n个数在很小的一个区间内, 平均时间复杂程度为O(n).
图5(桶排序示意图)
bucketSort(A) {
let B[0..n - 1] be a new array
n = A.length
for i = 0 to n - 1
make B[i] an empty list
for i = 1 to n
insert A[i] into list B[_nA[i]_]
for i = 0 to n - 1
sort list B[i] with insertion sort
concatenate the list B[0]...B[n - 1] together in order
}
radix sort
假设数组A中的元素都是d位数的整数,1是最小的位数,d是最高的位数。如图6是由d = 3 组成的数组
图6(radixSort示意图)
radixSort(A, d) {
for i = 1 to d
use a stable sort to sort array A on digit i
}
图7(排序算法总结)
//随机快排
quickSortRandom(A, p, r) {
if p < r
q = partitionRandom(A, p, r)
quickSortRandom(A, p, q - 1)
quickSortRandom(A, q + 1, r)
}
partitionRandom(A, p, r) {
x = random(p, r);
exchange A[x] with A[r]
return partition(A, p, r)
}