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

C语言顺序结构的二叉树之堆排序

一、堆1. 概念与分类上一期我们提到二叉树的实现既可以用顺序结构也可以用链式结构。本篇我们来学习顺序结构的二叉树起个新名字——堆heap。堆是完全二叉树它的底层是顺序结构的数组具有二叉树特性的同时还有一些其他性质堆分为大堆和小堆或称为大根堆、小根堆大堆大堆的每个结点的存储值都 它的子结点的存储值。小堆小堆的每个结点的存储值都 它的子结点的存储值。譬如在一个大堆中某一个父结点的值为20则它的子结点的值一定20在一个小堆中某一个父结点的值为20则它的子结点的值一定20。左孩子和右孩子的值的大小关系不确定。换句话说一个堆一定是大堆或小堆。以下的二叉树既不是大堆也不是小堆它们就不是堆2. 结构与性质定义数据结构堆123456typedefstructHeap{HPDataType* arr;intsize;intcapacity;}HP;上面的画图是用逻辑结构表示堆用存储结构表示堆就要用到数组了牢记二叉树结点的编号方式从上到下从左到右不难推断堆的数组中有下列性质大堆的首元素根结点是整个堆的最大值小堆的首元素根结点是整个堆的最小值。若子结点的下标为i则它的父结点是(i-1)/2。若父结点的下标为i则它的左孩子是2i1右孩子是2i2。结点个数是n2i1 n 说明无左孩子2i2 n 说明无右孩子。顺带给出堆的初始化和销毁方法以及后面要用到的交换两个变量值的方法12345678910111213141516171819202122voidHPInit(HP* php){assert(php);php-arr NULL;php-size php-capacity 0;}voidHPDestory(HP* php){assert(php);if(php-arr ! NULL)free(php-arr);php-arr NULL;php-size php-capacity 0;}voidSwap(HPDataType* px, HPDataType* py){HPDataType tmp *px;*px *py;*py tmp;}3. 入堆想要把一个新的数据插入堆分为两步把它插入堆数组末尾仅仅插入数据后可能会破坏堆的性质所以还要进行“向上调整”操作将新插入结点顺着其双亲往上调整位置至满足大堆或小堆的位置。我们以下面一个小堆为例插入一个新数据10如果它小于其父结点不符合小堆两者交换。再和新父结点比较如果小于交换……直到满足小堆所以我们要知道向上调整算法它有两个参数要被调整的堆数组要调整位置的结点的下标12345678910111213141516171819voidAdjustUp(HPDataType* arr,intchild){intparent (child - 1) / 2;//找这个结点的父结点while(child 0){//调整的是小堆: //调整的是大堆: if(arr[child] arr[parent]){Swap(arr[child], arr[parent]);child parent;parent (child - 1) / 2;}else//新数据已经到了对的位置{break;}}}这样我们就能实现入堆操作了12345678910111213141516171819voidHPPush(HP* php, HPDataType x){assert(php);if(php-size php-capacity)//空间不够则需增容{intnewcapacity php-capacity 0 ? 5 : 2 * php-capacity;HPDataType* tmp (HPDataType*)realloc(php-arr, newcapacity *sizeof(HPDataType));if(tmp NULL){perror(relloc fail!);exit(1);}php-arr tmp;php-capacity newcapacity;}php-arr[php-size] x;//新数据插到末尾即下标为size的位置AdjustUp(php-arr, php-size);php-size;}测试我们来实现一个小堆乱序给一些数将打印结果排列成堆的逻辑结构看看发现确实是正确的小堆4. 出堆我们所谓的出堆出的并不是数组末尾数据出的是第一个数据——堆的根结点。但是直接除去数组首元素再将后面元素的下标全体前挪会使堆的所有结点位置关系“大乱套”再想调整可就麻烦了。因此我们选择这样的出堆定元素方法先将堆顶数据和堆的最后一个数据交换size- -把数组末尾数据出掉再对堆顶元素进行“向下调整”操作。相比刚才所有结点位置大乱套这样只要调整一个结点的位置就好了。向下调整算法和向上调整类似它是比较结点和其较大或较小孩子的值不断往下交换调整位置直至满足大堆或小堆向下调整算法有三个参数要被调整的堆数组、要调整的结点的下标、堆的数据个数1234567891011121314151617181920212223242526voidAdjustDown(HPDataType* arr,intparent,intn){intchild 2 * parent 1;while(child n){//调整的是小堆: //调整的是大堆: if(child 1 n arr[child] arr[child 1])//找两个孩子中的较大/较小者{child;}//调整的是小堆: //调整的是大堆: if(arr[child] arr[parent]){Swap(arr[child], arr[parent]);parent child;child 2 * parent 1;}else//调整完成{break;}}}这样我们就能实现出堆操作了12345678voidHPPop(HP* php){assert(php);assert(php-size ! 0);//堆不能为空否则无数据可出Swap(php-arr[0], php-arr[php-size - 1]);//交换堆顶和堆尾数据php-size--;//将堆尾数据出掉AdjustDown(php-arr, 0, php-size);}测试我们来实现一个大堆乱序给一些数再进行一次出堆分析逻辑结构可以看到大堆实现成功出堆也没有问题二、堆排序堆排序是一种排序方法不是借助堆的数据结构而是利用堆的思想进行排序一个n个元素的数组假如想排升序就将数组建成一个大堆堆顶是最大值将堆顶和堆尾交换下标n-1处就是最大值了我们再把前n-1个数据调整成大堆此时堆顶就是第二大的数据堆顶和堆尾交换下标n-2处就是第二大值了……直至排序完成。相反地想排成降序就建小堆道理是一样的我们下面就以建成大堆为例。
http://www.rkmt.cn/news/1378921.html

相关文章:

  • c++中std::tuple、std::pair 、std::tie使用详解
  • 离心风机进风量与噪音平衡的结构设计方案:从声源抑制到系统级协同优化
  • DFT笔记60
  • 铜陵6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • 3分钟学会:如何在浏览器中零服务器依赖将HTML转为Word文档
  • 打造高效的技术学习环境:我的C#与C++跨语言混合编程实践之路
  • 5分钟快速部署i茅台自动化预约系统:免费开源的全能解决方案
  • 2026财务分析师如何提升自身专业能力:从财务建模到AI数据分析的进阶路线
  • 2026产品经理如何全面提升业务能力:关键步骤与成长路径
  • Unity ARCore开发避坑指南:从配置雷区到工业级AR落地
  • 06-大模型智能体开发工程师:大模型应用开发概述与发展脉络
  • 在SCnet上部署70b int4的模型
  • 终极指南:如何用OpenHRMS开源人力资源管理系统提升企业效率
  • 初创团队如何利用TaoToken统一管理多个AI项目的模型与成本
  • 基于ESP32与超声波的低成本无人机室内定位系统设计与实现
  • 初创公司如何借助 Taotoken 的 Token Plan 套餐优化 AI 研发成本结构
  • Multi-Agent系统实战:让多个Agent协作完成复杂任务
  • Frida逆向小程序云托管API通信链路实战
  • eqMac音频均衡器:核心功能与扩展模块配置指南
  • 模型训练中BatchSize大小对训练结果的影响
  • 如何快速定位Windows热键冲突:Hotkey Detective一键检测占用程序
  • 基于Intel Xe GPU与SYCL的AI模型完整性验证框架设计与优化
  • 抖音下载器终极指南:如何快速下载抖音视频和直播回放
  • 深入Linux时间管理:从主板上的RTC芯片到Ubuntu20.04的timedatectl,一次讲清楚
  • 3分钟快速上手:暗黑破坏神2存档编辑的终极免费工具指南
  • 从Bing日志到学术基准:MS MARCO数据集的前世今生与你的信息检索实验
  • 如何将B站缓存视频从m4s格式无损转换为通用MP4?
  • Java日常开发中常用的重要关键字
  • 基于ESP32与SGP30的室内空气质量监测系统DIY指南
  • 从零掌握Stellaris LM3S:ARM Cortex-M3微控制器实战开发指南