【数据结构】堆的实现以及建堆算法和堆排序

【数据结构】堆的实现以及建堆算法和堆排序

🔥个人主页大白的编程日记

🔥专栏数据结构


文章目录

  • 【数据结构】堆的实现以及建堆算法和堆排序
    • 前言
    • 一.堆的实现
      • 1.1 堆数据的插入
      • 1.2堆数据的删除
    • 二.建堆算法和堆排序
      • 2.1思路分析
      • 2.2向上建堆算法
      • 2.3向下调整建堆
      • 2.4堆排序
    • 后言

前言

哈喽,各位小伙伴大家好!上期给大家讲了树,二叉树以及堆。今天带着大家实现堆这个数据结构,以及堆排序。话不多说,咱们进入正题!向大厂冲锋!

一.堆的实现

  • 堆的定义
    我们用数组控制堆,在物理上是一个数组。逻辑上想象成堆。然后用size记录堆的节点个数。后面涉及扩容,所以用capacity记录数组空间大小。这里我们实现的是小堆
typedef int HPDataType;
typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;
  • 堆的初始化

初始化时我们可以先给堆开好空间,也可以不开。我们不开就先给NULL,然后size和capacity都先给0。

void HPInit(HP* php)
{assert(php);php->a = NULL;php->size = php->capacity = 0;
}//初始化
  • 堆的销毁

我们先free销毁数组,在把size和capacity置为0.

void HPDestroy(HP* php)
{assert(php);free(php->a);//销毁数组php->a = NULL;php->capacity = php->size = 0;
}//销毁

1.1 堆数据的插入

  • 思路分析

想要实现堆的插入,我们需要在数组插入数据后进行向上调整。

  • 堆数据插入
    插入数据前我们需要检查一下是否需要扩容。
    第一次没开空间,我们就给4个数据的空间。
    否则我们就realloc扩容为2倍。
    最后在赋值。然后size++更新节点个数。
    再用向上调整。
void HPPush(HP* php, HPDataType x)
{assert(php);//断言if (php->size == php->capacity)//空间满{int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc fail~");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size++] = x;//插入AdjustUp(php->a, php->size);//向上调整
}
  • 向上调整算法

我们size是数据个数,所以插入的child节点下标为size-1.那我们要找到他的父亲节点就是(child - 1) / 2。
然后判断插入数据和父亲节点的大小关系是否满足堆。
不满足就交换父子节点。然后更新child节点的下标。
满足则停止。或直到child节点到根节点时停止。

void AdjustUp(HPDataType* a, int size)
{int child = size - 1;//最后的节点while (child > 0){int parent = (child - 1) / 2;//父亲节点if (a[child] < a[parent])//判断{Swap(&a[child], &a[parent]);//交换child = parent;}else{break;//调整完成}}
}

1.2堆数据的删除

  • 思路分析

所以我们需要把最后一个节点和堆的根节点交换后,删除最后一个节点,然后向下调整。

  • 堆数据的删除
    我们先Swap交换根节点和最后一个节点,然后size–删除最后一个节点。再进行向下调整。
void HPPop(HP* php)//删除根节点
{assert(php);assert(php->size );//判断是否为空Swap(&php->a[0], &php->a[php->size-1]);//交换根节点和最后一个节点php->size--;//删除堆最后一个数据AdjustDown(php->a,php->size,0);//向下调整
}
  • 向下调整算法
    我们先算parent的左孩子child的下标。
    然后用假设法找出左右孩子最大或最小的那个孩子,注意有可能只有左孩子没有右孩子。所以我们用min+1<size判断是否存在右孩子。然后再将找出的最大或最小孩子与parent节点进行比较。如果不满足堆的大小关系就交换,然后更新parent的下标和新的child的下标。
    满足就break停止循环,或当child<=size说明此时parent为叶子节点停止循环。
void AdjustDown(HPDataType* a, int size,int parent)
{int child = parent * 2 + 1;//孩子节点while (child<size){int min = child;//左右孩子中最小的孩子if (min+1<size&&a[min] > a[min + 1])//防止没有右孩子{min = child + 1;}//假设法if (a[parent] > a[min])//判断{Swap(&a[parent], &a[min]);//交换parent = min;child = parent * 2 + 1;}else{break;//调整完毕}}
}
  • 堆的判空
    直接判断是否size为0
bool HPEmpyt(HP* php)
{assert(php);return php->size == 0;//判空
}
  • 堆的数据个数

直接返回size即可

int HPSize(HP* php)
{assert(php);return php->size;//返回数据个数
}
  • 堆顶元素

直接返回下标为0的位置数据即可。

HPDataType HPTop(HP* php)
{assert(php);assert(php->size);//判断是否为空return php->a[0];//返回根节点
}

二.建堆算法和堆排序

现在我们要实现堆排序,那我们需要建堆。
那升序建大堆还是小堆,降序建大堆还是小堆呢?还是都可以呢?
升序建大堆 降序建小堆 为什么呢?

2.1思路分析

那如何建堆呢?
有两种建堆算法。

2.2向上建堆算法

我们堆插入的过程其实就是建堆的过程。

for (int i = 1; i < n; i++)
{AdjustUp(p,i);
}

2.3向下调整建堆

我们从最后一个父亲节点依次往后向下调整

for (int i = (n - 1 - 1) / 2; i >= 0; i--)
{AdjustDown(p, n, i);
}

2.4堆排序

实现堆排序,我们升序建大堆,降序建小堆。
两种建堆算法都可以。
然后我们用end表示最后一个堆元素
每次循环交换堆顶元素和最后一个堆元素。
然后堆顶元素向下调整。更新最后一个堆元素即可。

void HeapSort(HPDataType* p, int n)
{for (int i = 1; i < n; i++)//向上建堆{AdjustUp(p,i);}int end = n - 1;//最后一个堆元素while (end > 0)//{Swap(&p[0], &p[end]);//交换堆顶元素和最后一个堆元素AdjustDown(p,end,0);//向下调整end--;//更新最后一个堆元素}
}
  • 验证
void HeapSort(HPDataType* p, int n)
{for (int i = 1; i < n; i++)//向上建堆{AdjustUp(p,i);}int end = n - 1;//最后一个堆元素while (end > 0)//{Swap(&p[0], &p[end]);//交换堆顶元素和最后一个堆元素AdjustDown(p,end,0);//向下调整end--;//更新最后一个堆元素}
}
void test2()
{int a[] = { 9,6,4,7,10,5,3,1,2,8};HeapSort(a, sizeof(a) / sizeof(a[0]));for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++){printf("%d ", a[i]);}
}
int main()
{test2();return 0;
}

后言

这就堆的实现以及建堆算法和堆排序。这都是数据结构的重中之重。
大家一定要多加掌握。今天就分享到这,感谢各位大佬的耐心垂阅!咱们下期见!拜拜~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java的转义字符,注释和代码规范

目录 1.Java运行机制 Java开发快速入门 Java开发注意事项和细节说明 Java学习方法 2.Java的转义字符 Java常用的转义字符 代码示例&#xff1a; 转义字符练习 3.初学java易犯错误 4.注释&#xff08;comment&#xff09; 单行注释与多行注释 文档注释 5.Java代码规…

Spark轨迹大数据处理_scalaSpark代码实两个GIS点(经纬度点)之间的方位角计算

终于有时间来搞一搞这个专栏了 首先声明一下 1、我这个代码是基于一个简化方位角模型&#xff0c;忽略了地球的曲率&#xff0c;适用于距离相对较短的距离。因为业务相关&#xff0c;这个方位角两个点的距离计算不会超过1000km。 2、我这个方位角的计算逻辑&#xff1a;是从一…

使用Top进行设备性能分析思路

Top命令 像windows一样&#xff0c;linux也有一个“进程管理”&#xff0c;可以在命令行执行 top &#xff0c;就可以整体的查看当前机器的资源及进程情况。 在性能问题中&#xff0c;Top是使用较多的一个命令&#xff0c;一般用它可以从整体上了解系统的CPU、内存、IO情况&am…

MongoDB教程(十七):MongoDB主键类型ObjectId

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、Object…

【状态机动态规划 状态压缩】1434. 每个人戴不同帽子的方案数

本文涉及知识点 位运算、状态压缩、枚举子集汇总 动态规划汇总 LeetCode 1434. 每个人戴不同帽子的方案数 总共有 n 个人和 40 种不同的帽子&#xff0c;帽子编号从 1 到 40 。 给你一个整数列表的列表 hats &#xff0c;其中 hats[i] 是第 i 个人所有喜欢帽子的列表。 请你…

建投数据人力资源系列产品获得欧拉操作系统及华为鲲鹏技术认证书

近日&#xff0c;经欧拉生态创新中心和华为技术有限公司测评&#xff0c;建投数据自主研发的人力资源管理系统、招聘管理系统、绩效管理系统、培训管理系统&#xff0c;完成了基于欧拉操作系统openEuler 22.03、华为鲲鹏Kunpeng 920&#xff08;Taisha 200&#xff09;的兼容性…

ASP.NET MVC

ASP.NET MVC与.NET Framework关系 .NET Framework是一个庞大的代码库&#xff0c;能为多种编程语言提供支持(如C#、VB、F#等)。同时.NET Framework 提供了多种技术框架&#xff0c;ASP.NET MVC是.NET Framework提供的众多技术框架中的一种&#xff0c;用于开发Web应用。 .NET …

B端:小小详情页蕴藏大学问,附大量案例 。

在B端&#xff08;Business-to-Business&#xff0c;即企业与企业之间的商业模式&#xff09;的设计中&#xff0c;详情页是一个非常重要的环节。虽然它可能看起来只是一个简单的页面&#xff0c;但实际上其中蕴藏着许多大学问。 用户需求与体验&#xff1a; 在B端设计中&…

【Docker】Docker-consul容器服务自动发现与注册

目录 一.Consul概述 1.解决了什么问题 2.什么叫微服务或者注册与发现 3.consul的模式 4.相关命令 二.consul 部署 1.consul服务器部署 2.部署docker容器 3.Nginx负载均衡器 3.1.安装启动nginx 3.2.配置nginx负载均衡 3.3.创建配置consul complate模板文件 3.4.添加…

基于Qt的上位机通用框架

0.前言 最近一年多的时间一直在开发设备控制相关的软件&#xff0c;加上之前在聚光的两年时间&#xff0c;前前后后开发这种设备控制类型的上位机软件也有三年的时间了。总结出了一套基于Qt的上位机编程框架&#xff0c;核心思想类似于C#的依赖注入&#xff0c;对象的初始化都…

JavaScript青少年简明教程:流程控制语句

JavaScript青少年简明教程&#xff1a;流程控制语句 JavaScript 提供了一系列的流程控制语句&#xff0c;用于控制代码的执行顺序。 条件语句 条件语句根据表达式的真假来执行不同的代码块。 if 语句 用于在条件为真时执行代码块。 语法&#xff1a; if(条件){ 条件满足执…

微信小程序获取蓝牙并实现内容打印

通过微信小程序如何实现获取蓝牙打印机并实现打印能力&#xff0c;之前做过一个测试Dome&#xff0c;能够获取附近的蓝牙打印机设备并实现打印,今天开放出来供大家参考。 wxml <!--右下角搜索--> <view class"ly-cass-box"><view class"ly-cas…

Hadoop、HDFS、MapReduce 大数据解决方案

本心、输入输出、结果 文章目录 Hadoop、HDFS、MapReduce 大数据解决方案前言HadoopHadoop 主要组件的Web UI端口和一些基本信息MapReduceMapReduce的核心思想MapReduce的工作流程MapReduce的优缺点Hadoop、HDFS、MapReduce 大数据解决方案 编辑 | 简简单单 Online zuozuo 地址…

广义线性模型(1)广义线性模型详解

一 GLM概述 广义线性模型&#xff08;Generalized Linear Models&#xff0c;GLM&#xff09;由 Nelder 和 Wedderburn 于 1972年提出和发表 &#xff0c;旨在解决普通线性回归模型无法处理因变量离散&#xff0c;并发展能够解决非正态因变量的回归建模任务的建模方法。 在广…

数据结构:二叉搜索树(简单C++代码实现)

目录 前言 1. 二叉搜索树的概念 2. 二叉搜索树的实现 2.1 二叉树的结构 2.2 二叉树查找 2.3 二叉树的插入和中序遍历 2.4 二叉树的删除 3. 二叉搜索树的应用 3.1 KV模型实现 3.2 应用 4. 二叉搜索树分析 总结 前言 本文将深入探讨二叉搜索树这一重要的数据结构。二…

【PyTorch】单目标检测项目

对象检测是在图像中查找特定对象位置的过程,用于处理单对象或多对象检测问题。单对象检测在给定图像中仅定位一个对象。对象的位置可以通过边界框定义。单对象检测使用四个数字预测边界框。对于正方形物体&#xff0c;可以固定宽度和高度&#xff0c;并简化问题以仅预测两个数字…

Unity:PC包直接查看Log日志

PC端会输出Log日志&#xff0c;位置在&#xff1a; C:\Users\用户名\AppData\LocalLow\公司名\项目名 在这里可以找到类似的文件&#xff1a; 打开便可以看到打印。

解决 elementUI 组件在 WebStorm 中显示为未知标签的问题

解决 elementUI 组件在 WebStorm 中显示为未知标签的问题 一、问题 自从转到 ts 之后&#xff0c;编辑器就一直提示用到的 elementUI 标签未知&#xff0c;一直显示一溜黄色警示&#xff0c;很烦&#xff1a; 二、解决 把它改成大写就可以了。 如下&#xff1a; 把整个项目…

springboot实战(十二)之通过注解的方式记录接口出入参log入库

前言 生产过程中&#xff0c;为了更好的辅助线上问题排查避免不了对接口出入参进行日志输出的时候&#xff0c;并且为了分析接口数据效果需要将每次请求接口的出入参进行落库方便后续的数据分析&#xff0c;这时总不能每个接口入参之后、出参之前都打印一遍日志吧&#xff1f;如…

51单片机嵌入式开发:16、STC89C52RC 嵌入式之 步进电机28BYJ48、四拍八拍操作

STC89C52RC 嵌入式之 步进电机28BYJ48、四拍八拍操作 STC89C52RC 之 步进电机28BYJ48操作1 概述1.1 步进电机概述1.2 28BYJ48概述 2 步进电机工作原理2.1 基本原理2.2 28BYJ48工作原理2.3 28BYJ48控制原理 3 电路及软件代码实现4 步进电机市场价值 STC89C52RC 之 步进电机28BYJ…