🚩 堆排序
定义
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。除了最低级别外所有级别都满了,如果最低级别未满,则必须将节点打包到左侧
二叉堆的性质
给定一个节点数为n,高度为h的二叉堆
- n ∈ [ 2 h , 2 h + 1 − 1 ] n \in [2^h, 2^{h+1} -1] n∈[2h,2h+1−1]
- 高度 h = O ( l o g ( n ) ) h = O(log(n)) h=O(log(n))
数组实现二叉堆
在 i i i 处有一个节点 x x x
- 左孩子在 2 i + 1 2 i+1 2i+1
- 右孩子在 2 i + 2 2 i+2 2i+2
- 父节点在
(
i
−
1
)
/
2
(i-1)/2
(i−1)/2
大堆
子结点的键值或索引总是小于它的父节点
小堆
子结点的键值或索引总是大于它的父节点
大堆的建立
小堆建立同理
deleteMax
使用A[n-1]代替A[0], 然后与下面的节点比较,往下交换位置,满足大顶堆性质即可
deleteMin同理
🚩 C语言的实现
1. 大堆的建立
bool InsertMax(int *A, int size, int x){
int hole = size++;
while (hole > 0 && x > A[(hole - 1)/2]){ // compare the node to its parent
A[hole] = A[(hole - 1) / 2]; // change the location of the nodes
hole = (hole - 1) / 2;
}
A[hole] = x; // assign the correct location to x
return true;
}
2. 小堆的建立
bool InsertMin(int *A, int size, int x){
int hole = size++;
while (hole > 0 && x < A[(hole - 1) / 2]){ // compare the node to its parent
A[hole] = A[(hole - 1) / 2]; // change the location of the nodes
hole = (hole - 1) / 2;
}
A[hole] = x; // assign the correct location to x
return true;
}
3. deleteMax
int deleteMax(int *A, int size){
if (size == 0){ // the heap is empty
return -1;
}
int max = A[0];
int hole = 0;
int x = A[--size];
// percolate down
while (2 * hole + 1 < size){ // find left child
int sid;
// let sid be the index of A[hole]'s larger child
if (2 * hole + 2 < size){ // find right child
sid = A[2 * hole + 1] > A[2 * hole + 2] ? 2 * hole + 1 : 2 * hole + 2;
}
else{
sid = 2 * hole + 1;
}
// find the correct hole, stop the loot
if (x >= A[sid]){
break;
}
A[hole] = A[sid]; // change the location of the nodes
hole = sid;
}
A[hole] = x; // assign the correct location to x
return max;
}
4. deleteMin
int deleteMin(int *A, int size){
if (size == 0){ // the heap is empty
return -1;
}
int min = A[0];
int hole = 0;
int x= A[--size];
// percolate down
while (2 * hole + 1 < size){ // find left child
int sid;
// let sid be the index of A[hole]'s larger child
if (2 * hole + 2 < size){ // find right child
sid = A[2 * hole + 1] < A[2 * hole + 2] ? 2 * hole + 1 : 2 * hole + 2;
}
else {
sid = 2 * hole + 1;
}
// find the correct hole, stop the loot
if (x <= A[sid]){
break;
}
A[hole] = A[sid]; // change the location of the nodes
hole = sid;
}
A[hole] = x; // assign the correct location to x
return min;
}
5. 堆排序
降序用小堆,升序用大堆
// 升序
void HeapSort(int *A, int n) {
for(int i = 0; i < n; i++) {
InsertMax(A, i, A[i]);
}
for (int i = n - 1; i >= 0; i--){
A[i] = deleteMax(A, i+1);
}
}
// 降序
void HeapSort(int *A, int n) {
for(int i = 0; i < n; i++) {
InsertMin(A, i, A[i]);
}
for (int i = n - 1; i >= 0; i--){
A[i] = deleteMin(A, i+1);
}
}
🚩 时间复杂度分析
- 生成二叉堆: O ( n l o g n ) O(nlogn) O(nlogn)
- deleteMax / deleteMin: O ( n l o g n ) O(nlogn) O(nlogn)
- 数组复制: O ( n ) O(n) O(n)
The Best Case:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
The Worst Case:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
The Average Case:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
📖 以上均为个人学习数据结构算法时的小笔记,如有错误请多多指正