其他
图解堆排序算法
The following article is from 小K算法 Author 小K算法
演进
除去最后一层之后的子树为满二叉树,且最后一层结点依次从左到右分布,则称为完全二叉树。
每个结点都大于等于其子结点,称为大根堆。
每个结点都小于等于其子结点,称为小根堆。
02
堆存储
int value;
Node *lson, *rson;
};
Node *heap;
以下思想都以大根堆举例
03
堆调整
先比较是否大于父结点,如果大于就进行交换,并将指针上移到父结点
int heapUp(int *heap, int k) {
int parent, son, x;
x = heap[k];
son = k;
parent = (son - 1) / 2;
while (son > 0) {
//如果父结点大于等于heap[k]则退出,否则将父结点下移
if (heap[parent] >= x)
break;
heap[son] = heap[parent];
son = parent;
parent = (son - 1) / 2;
}
heap[son] = x;
return 0;
}
先比较两个子结点哪个更大,取出更大的子结点
再比较更大的子结点是否大于父结点,如果大于就进行交换,并将指针下移
int heapDown(int *heap, int k, int n) {
int parent, son, x;
x = heap[k];
parent = k;
son = 2 * k + 1; //左孩子结点
while (son <= n) {
//比较左右儿子,选择较大的一个
if (son + 1 <= n && heap[son + 1] > heap[son])
son++; //使son指向左右孩子中较大的结点。
//如果儿子结点中较大的都小于等于待调整结点则退出,否则将子结点上移
if (heap[son] <= x)
break;
heap[parent] = heap[son];
parent = son;
son = 2 * parent + 1;
}
heap[parent] = x;
return 0;
}
04
增减元素
05
构建堆
插入一个元素要调整的高度为logi,所以插入n个元素的总次数为log1+log2+...+logn=log(n!)。
倒数第二层有2^(h-2)个结点,调整高度为1,依次类推,第一层有1个结点,调整高度为h-1,整体加起来的复杂度为O(n)。
for (int i = (n - 1) / 2; i >= 0; --i) {
heapDown(heap, i, n);
}
}
06
排序
将堆顶与堆尾的元素置换
整体元素长度减1 对堆顶元素进行向下调整
int temp;
temp = heap[a];
heap[a] = heap[b];
heap[b] = temp;
}
void heapsort(int *heap, int n) {
for (int i = n; i > 0; --i) {
swap(heap, 0, i);
heapDown(heap, 0, i - 1);
}
}
07
总结
- EOF -
觉得本文有帮助?请分享给更多人
推荐关注「算法爱好者」,修炼编程内功
点赞和在看就是最大的支持❤️