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

堆排序-调整算法

个人主页点这里!~


1.堆


了解堆排序首先要了解一下这个数据结构

堆(Heap)是一种特殊的树形数据结构,它通常被表示为一个完全二叉树或近似完全二叉树,并且满足堆性质(Heap Property)。堆主要分为两种:大堆(Max Heap)和小堆(Min Heap)。

我们有一个待排序数组{5,4,7,9,3,2,6,1},将他层序遍历为堆,如下图

在堆中,我们在做一个大堆要保证大的元素始终在小的上面,做一个小堆时,要保证小的元素始终在大的上面,所以我们需要实现两种调整函数:

  1. 向上调整(adjustup)

    • 操作方向:从子节点向父节点移动数据。
    • 目的:当在堆的底部插入一个新的元素时,或者当一个元素的值增加并可能破坏堆的性质时,需要向上调整来保持堆的性质。具体来说,如果一个节点的值大于其父节点的值(在最大堆中),或者小于其父节点的值(在最小堆中),那么这个节点就需要与其父节点交换位置,并且这个过程可能需要继续向上进行,直到堆的性质被恢复。
      void AdjustUp(HPDataType* a, int child)
      {int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent])//СڽС{Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
      }
      
  1. 向下调整(adjustdown)

    • 操作方向:从父节点向子节点移动数据。
    • 目的:当从堆顶删除一个元素(通常是根节点),或者当一个元素的值减小并可能破坏堆的性质时,需要向下调整来保持堆的性质。具体来说,新的根节点(或从堆的末尾移到根节点的元素)可能与它的子节点之一或两个都不满足堆的性质,这时就需要将这个节点与其较大的子节点(在最大堆中)或较小的子节点(在最小堆中)交换位置,并且这个过程可能需要继续向下进行,直到堆的性质被恢复。
      void AdjustDown(HPDataType* a, int n, int parent)
      {int child = parent * 2 + 1;while (child < n){if (a[child] > a[child + 1] && child + 1 < n){child++;}if (a[child] < a[parent])//СڽС{Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
      }
      

2.堆排序(排升序)

我们如何利用堆这个结构实现排序呢?

第一步:建堆

  1. 那我们排升序是建大堆还是建小堆呢?

先说结论排升序建大堆,降序建小堆

我们先用反证法:我们排升序建一个小堆,看看会出现什么情况

我们排升序此时1,2,3,4,5位置已经正确了,但我们排剩下的数据时无法高效的排序,难道把剩下的数据拿出来再建堆,那消耗就太大了,并且节点之间关系全乱了,兄弟变父子,父亲变兄弟(我把你当兄弟,你却想当我爸爸)(比如7和6,本来是兄弟,再建堆就变成了兄弟)

所以我们不能建小堆,应该建大堆,那大堆的性质帮助我们如何解决你?看第二步

第二步:排序

我们建一个大堆

因为我们建一次大堆将最大的元素放到了堆顶

所以我们首先将堆顶的最大元素与最后一个元素交换位置,

然后把最大的元素踢出,因为在最后,所以堆不会产生向上面的问题

最后再建大堆,就找出第二大的元素在堆顶,如此往复

//   堆排序
void HeapSort(int* a, int n)
{
// 总结:升序建大堆 
//      降序建小堆for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}
//2.向下调整排序int end = n - 1;while (end > 0)//一次循环把最小值排出(小堆的性质:小的永远在上面){Swap(&a[0], &a[end]);// 选出次小的--end;AdjustDown(a, end, 0);}
}

分享到这里   个人主页点这里!~

相关文章:

  • wireshark 标记自己想要的数据包
  • C++ OpenCV 图像分类魔法:探索神奇的模型与代码
  • 【上篇】从 YOLOv1 到 YOLOv8 的 YOLO 物体检测模型历史
  • 用git下载hugging face上的大模型,以Qwen1.5-7B为例
  • webservice、WCF、webAPI、MVC权限认证
  • 型号FM152A,FM148R和利时
  • 【软件工程】第七章
  • Flink⼤状态作业调优实践指南:状态报错与启停慢篇
  • 中缀表达式和前缀后缀
  • “安全生产月”专题报道:AI智能监控技术如何助力安全生产
  • C/C++ 引用和指针的区别及使用场景
  • QT中将资源文件(image、qss、qm等)封装到静态库中,程序该如何引用静态库中的资源文件
  • mysql8 .net sqlsuger 批量插入dbScope.Fastest<T>().PageSize(2000).BulkCopy(T)>
  • Elasticsearch 认证模拟题 - 10
  • 【ARM Cache 与 MMU 系列文章 7.7 – ARMv8/v9 MMU Table 表分配原理及其代码实现 1】
  • 【node学习】协程
  • Android开源项目规范总结
  • Docker下部署自己的LNMP工作环境
  • EOS是什么
  • extract-text-webpack-plugin用法
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • JavaScript 奇技淫巧
  • select2 取值 遍历 设置默认值
  • spring-boot List转Page
  • 测试如何在敏捷团队中工作?
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 记一次用 NodeJs 实现模拟登录的思路
  • 简析gRPC client 连接管理
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 利用DataURL技术在网页上显示图片
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 十年未变!安全,谁之责?(下)
  • 线性表及其算法(java实现)
  • 用Python写一份独特的元宵节祝福
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​ubuntu下安装kvm虚拟机
  • # .NET Framework中使用命名管道进行进程间通信
  • #数据结构 笔记一
  • #微信小程序(布局、渲染层基础知识)
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • $().each和$.each的区别
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (二)WCF的Binding模型
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (四) Graphivz 颜色选择
  • (四)stm32之通信协议
  • (一)Dubbo快速入门、介绍、使用
  • *2 echo、printf、mkdir命令的应用
  • ... 是什么 ?... 有什么用处?