当前位置:网站首页>2. 堆排序『较难理解的排序』
2. 堆排序『较难理解的排序』
2022-07-07 13:03:00 【牟泉禹[Dark Cat]】
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。这个堆是一个近似完全二叉树的结构,并且还是个大顶堆,排序也是根据这个大顶堆来进行的。
为什么说 堆排序 比较难理解呢?答:主要原因是 有些人 可能没学过 二叉树,更不知道什么是 堆,更没学过 模拟数组的思想。也就是说 他在没有这些 前提知识点的情况下,怎么可能 好的理解 堆排序呢。更何况 堆排序 调整堆那里的实现,还 用到了 我们最头大的递归。而且 整体的排序思路,一旦 讲师 没有讲清楚,可能 就 是一知半解的。
1.1 算法描述
- 用数组模拟二叉树结构,使得每个根节点的左右节点 对应下标为
left = 2k + 1
、right = 2k + 2
。 - 将这个二叉树 初始化为 大顶堆,这里要 用到 递归的操作。思想是 从最后的那个子树开始,往前 把每个 子树 都变为大顶堆!当然还会有 后效性问题(
即 当我们 调整了节点顺序后,被交换的这个节点 作为根节点的那个子树 是否还是 大顶堆呢??
),所以 我们 这里 就需要 递归,然后 去 处理 该节点下面的所有子树。 - 由于 整个二叉树的根节点 是 最大的值,所以我们 可以 把 这个节点 和 最后 一个节点 进行交换。即 在 1 ~ n 个节点的范围内,这个 根节点 是 最大值,我们将它 放在 最后。然后 我们再把 1 ~ n – 1 个节点范围的二叉树(排除 最后一个节点)让其再次变为 大顶堆,然后 再去 进行 上述的操作,把倒数第二个 最大值 放到了 倒数第二的位置。以此类推,当我们 处理到只剩下 第一个节点的二叉树的时候,则整体 有序!!
1.2 动图演示
1.3 代码实现
#include <iostream>
#include <vector>
#include <math.h>
#include <algorithm>
using namespace std;
vector<int> arr = {
91,60,96,13,35,65,46,65,10,30,20,31,77,81,22};
int len;
void swapF(int k){
// 对以 k 为 根节点 的子树 进行 探索 和 调整
int left = 2 * k + 1;
int right = 2 * k + 2;
int father = k;// 待更新的 根节点,可能 根节点 需要 调整更新
if(left < len && arr[left] > arr[father]){
father = left;// 左节点 比 根节点 大,所以 左节点的下标 保存到
// father 里,提前 预备 根节点的位置
}
if(right < len && arr[right] > arr[father]){
father = right;// 若 最大的节点 是 右节点,那么 father = right
}
if(father != k){
// 如果 该子树进行了 调整,即 根节点 发生变化
// 那么就要 处理 后效性问题
swap(arr[father],arr[k]);// 先将 这颗子树进行调整
swapF(father);// 然后 来 看下 被我们交换的节点的位置 数据发生了
// 变化后,是否 还 保持 着大顶堆的 性质
}
}
void init(){
len = arr.size();
for(int i = floor(len / 2);i >= 0; i--){
// 从 最后一个 子树开始
swapF(i);
}
}
void heapSort(){
init();
for(int i = len - 1;i > 0;--i){
// 进行 排序,把每一个 区间内 最大的值,都 放到 该放的位置
swap(arr[i],arr[0]);
len--;
swapF(0);
}
}
int main(void){
heapSort();
for(auto x : arr){
cout << x << " ";
}
return 0;
}
堆排序 分为两个部分:堆的调整 + 堆的排序。
时间复杂度:O(n) + O(nlogn) = O(nlogn)
空间复杂度:O(1)
边栏推荐
- [Yugong series] go teaching course 005 variables in July 2022
- leetcode:648. Word replacement [dictionary tree board + find the shortest matching prefix among several prefixes]
- Five pain points for big companies to open source
- Today's sleep quality record 78 points
- leetcode 241. Different Ways to Add Parentheses 为运算表达式设计优先级(中等)
- CTFshow,信息搜集:web3
- Ctfshow, information collection: web8
- The method of parsing PHP to jump out of the loop and the difference between continue, break and exit
- Es log error appreciation -trying to create too many buckets
- 【跟着江科大学Stm32】STM32F103C8T6_PWM控制直流电机_代码
猜你喜欢
Summer safety is very important! Emergency safety education enters kindergarten
CTFshow,信息搜集:web6
Ctfshow, information collection: web2
⼀个对象从加载到JVM,再到被GC清除,都经历了什么过程?
CTFshow,信息搜集:web13
WebRTC 音频抗弱网技术(上)
Notes HCIA
Discussion on CPU and chiplet Technology
Apache multiple component vulnerability disclosure (cve-2022-32533/cve-2022-33980/cve-2021-37839)
Ctfshow, information collection: web12
随机推荐
"July 2022" Wukong editor update record
上半年晋升 P8 成功,还买了别墅!
asp.netNBA信息管理系统VS开发sqlserver数据库web结构c#编程计算机网页源码项目详细设计
Ctfshow, information collection: web13
[today in history] July 7: release of C; Chrome OS came out; "Legend of swordsman" issued
Stream learning notes
什么是数据泄露
CTFshow,信息搜集:web14
@Introduction and three usages of controlleradvice
Niuke real problem programming - Day12
众昂矿业:萤石继续引领新能源市场增长
CTFshow,信息搜集:web10
Lidar Knowledge Drop
CTFshow,信息搜集:web7
什么是云原生?这回终于能搞明白了!
C 6.0 language specification approved
13 ux/ui/ue best creative inspiration websites in 2022
A laravel background management expansion package you can't miss - Voyager
什么是pv和uv? pv、uv
Apache多个组件漏洞公开(CVE-2022-32533/CVE-2022-33980/CVE-2021-37839)