当前位置: 首页 > ops >正文

堆排序的详细解读

一.堆的基本概念

1.什么是堆

堆是一种特殊的完全二叉树,满足一下性质:

  • 最大堆每个节点的值都大于或等于其子节点的值(堆顶元素最大)
  • 最小堆:每个节点的值都小于或等于其子节点的值(堆顶元素最小)

其中,堆排序常使用最大堆来进行升序排序

 2.堆的存储

堆常用数组进行存储,对于数组中第i个元素:

  • 父节点的位置:(i-1)/2
  • 左节点的位置:2*i+1
  • 右节点的位置:2*i+2

二、堆排序的基本思想

堆排序的基本思想分为两个主要步骤:
1. 建堆:将无序数组构建成一个最大堆
2. 排序:重复从堆中取出最大元素(堆顶),然后调整剩余元素使其重新成为最大堆

三、堆排序的详细步骤

 1. 构建最大堆
从最后一个非叶子节点开始(即n/2 - 1),向前依次对每个节点执行"下沉"操作,确保以该节点为根的子树满足堆的性质。

下沉操作:
1. 比较当前节点与其左右子节点
2. 如果当前节点小于某个子节点,则与较大的子节点交换
3. 继续向下比较,直到当前节点大于等于其子节点或到达叶子节点

2. 排序过程
1. 将堆顶元素(最大值)与堆的最后一个元素交换
2. 堆的大小减1(排除已排序的元素)
3. 对新的堆顶元素执行下沉操作,恢复堆的性质
4. 重复上述过程,直到堆中只剩一个元素

演示: 

 

四、堆排序的代码实现

#include<iostream>
#include<algorithm>using namespace std;//重建堆
void adjust(int a[],int start,int end)
{int temp=a[start];    //根节点for(int i=2*start+1;i<=end;i=i*2+1)   //从左子树开始{if(i<end&&a[i]<a[i+1])    //如果右子树大于左子树,则i指向右子树{i++;}if(a[i]>temp)    //如果子节点大于根节点,则将子节点的值赋给根节点{a[start]=a[i];start=i;}else    //如果子节点小于根节点,则跳出循环{break;}}a[start]=temp;    //将根节点的值赋给子节点
}//堆排序
void heapsort(int a[],int n)
{//建立大根堆for(int i=n/2-1;i>=0;i--)   //从最后一个非叶子节点开始{adjust(a,i,n-1);    //调整堆}//交换堆顶和堆底元素,重新调整堆for(int i=n-1;i>0;i--){swap(a[0],a[i]);    //交换堆顶和堆底元素adjust(a,0,i-1);    //调整堆}
}int main()
{int a[]={46,55,13,42,94,17,5,70};int n=sizeof(a)/sizeof(a[0]);heapsort(a,n);for(int i=0;i<n;i++){cout<<a[i]<<" ";}return 0;
}

五、堆排序的优缺点

优点:
1. 时间复杂度稳定为O(n log n),没有最坏情况
2. 空间复杂度低,是原地排序算法
3. 适合处理大规模数据

 缺点:
1. 不稳定排序算法(相同元素的相对位置可能改变)
2. 在数据量较小的情况下,常数因子较大,可能不如插入排序等简单算法快
3. 数据访问方式不够局部化(缓存不友好)

六、堆排序的应用场景

1. 需要稳定O(n log n)时间复杂度的场景
2. 内存受限的环境(因为它是原地排序)
3. 需要同时进行插入和提取最大/最小值的场景(优先队列)
4. 实时系统,因为最坏情况性能好

http://www.xdnf.cn/news/12535.html

相关文章:

  • 5.3.2_2二叉树的线索化
  • 物联网协议之MQTT(二)服务端
  • web端rtmp推拉流测试、抽帧识别计数,一键式生成巡检报告
  • 【第六篇】 SpringBoot的日志基础操作
  • 主流大语言模型安全性测试(三):阿拉伯语越狱提示词下的表现与分析
  • 408第一季 - 数据结构 - 树与二叉树
  • 数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
  • btstack协议栈---Ubuntu驱动CSR8510 USB Dongle
  • 数学:花括号在数学中的应用详解
  • 35 C 语言字符串转数值函数详解:strtof、strtod、strtold(含 errno 处理、ERANGE 错误)
  • Ubuntu挂载本地镜像源(像CentOS 一样挂载本地镜像源)
  • 什么是高考?高考的意义是啥?
  • Ubuntu下有关UDP网络通信的指令
  • Linux 下关于 ioremap 系列接口
  • 虚幻引擎5-Unreal Engine笔记之SET节点的输出引脚获取设置后的最新变量值
  • 【力扣链表篇】19.删除链表的倒数第N个节点
  • ASTRA论文总结
  • PDF转PPT转换方法总结
  • 移除元素-JavaScript【算法学习day.04】
  • 基于Java Swing的办公自动化系统设计与实现:附完整源码与论文
  • Deepseek基座:Deepseek-v2核心内容解析
  • 【C/C++】STL实现版本为什么比手写版本高?
  • Spring Cloud 多机部署与负载均衡实战详解
  • 向 AI Search 迈进,腾讯云 ES 自研 v-pack 向量增强插件揭秘
  • 通俗解释Linux 动态库-fPIC的作用
  • Dynamics 365 Finance + Power Automate 自动化凭证审核
  • 通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
  • Python 自定义函数详解及递归函数等案例
  • 协议哨兵:场景化协议风险的ai工具
  • Tableau for mac 驱动