数据结构-二叉树-堆

一、物理结构和逻辑结构

在内存中的存储结构,逻辑结构为想象出来的存储结构。

二、完全二叉树的顺序存储结构

parent = (child - 1)/2

leftchild = 2*parent + 1;

rightchild = 2*parent +2

上面的顺序结构只适合存储完全二叉树。如果存储,会浪费很多的空间。

三、堆

1、堆的分类

小根堆:树中所有的父亲都小于或等于孩子。

大根堆:树中所有的父亲都大于或等于孩子。

接下来我们需要定义一个堆。定义过程如下:

创建堆的时候会涉及到一个向上调整的算法:我们可以画图表示这一过程

void UpAdjust(HPDataType* a, int child)
{assert(a);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;}}
}

删除堆顶数据需要涉及到向下调整

这里不能挪动数据。原因有两个,效率低下,父子兄弟关系全乱了。

思路就是:把头部数据和尾部数据交换。删除尾部数据,然后进行向下调整

这样删除的优点是 效率高,保持了大部分堆的父子关系。

向下调整的过程中我们需要和儿子中最大的进行比较。这样才能保证堆的关系不变。

没有孩子时结束,转换一下就是child < size。

void DownAdjust(HPDataType* a,int parent,int size)
{int child = 2 * parent + 1;while (child < size){	//选出最大的那一个孩子if (child + 1 < size && a[child] < a[child + 1]){child++;}if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}

整体实现

#include "heap.h"void HeapInit(HP* hp)
{assert(hp);hp->a = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);hp->size = 0;hp->capacity = SIZE;
}void AddCapacity(HP* hp)
{assert(hp);if (hp->size == hp->capacity){HPDataType* temp = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * hp->capacity * 2);if (temp == NULL){perror("realloc failed");return;}hp->a = temp;hp->capacity *= 2;}
}
void Swap(int* left, int* right)
{int temp = *left;*left = *right;*right = temp;
}
//除了child的位置,前面的数据构成堆
void UpAdjust(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;}}
}void HeapPush(HP* hp, HPDataType x)
{//考虑扩容的问题AddCapacity(hp);//插入数据hp->a[hp->size++] = x;//还需要考虑向上调整的问题。UpAdjust(hp->a, hp->size - 1);
}void DownAdjust(HPDataType* a,int parent,int size)
{int child = 2 * parent + 1;while (child < size){	//选出最大的那一个孩子if (child + 1 < size && a[child] < a[child + 1]){child++;}if (a[child] > a[parent]){//交换两个数字Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}
//删除头部的数据
void HeapPop(HP* hp)
{assert(hp);assert(!HeapEmpty(hp));//首先交换头和尾的数字Swap(&hp->a[0], &hp->a[hp->size-1]);//然后删除尾的数字hp->size--;//向下调整恢复堆的原型 向下调整的左右子树一定是堆DownAdjust(hp->a, 0, hp->size);
}HPDataType HeapTop(HP* hp)
{assert(hp);return hp->a[0];
}
bool HeapEmpty(HP* hp)
{assert(hp);return hp->size == 0;
}
int HeapSize(HP* hp)
{assert(hp);return hp->size;
}

四、堆排

对数组进行排序。我们可以把它直接搞成一个堆,建堆操作

1、向上调整建堆

(1)把第一个数看成一个堆中的数。后来的数进行向上调整建立堆。 O(nlogn)

(2)排升序需要建大堆,减小堆关系就都乱了

利用向上调整建大堆时我们可以交换堆头和堆尾的值。然后在进行向下调整选出次小的值,如此往复。

堆排的过程如下

堆排代码:

void HeapSort(int* a,int n)
{//首先建立大堆for (int i = 1; i < n; i++){UpAdjust(a, i);}//交换堆头和堆尾的数字选出最大的数字放到堆尾//然后向下调整int end = n - 1;while (end > 0){Swap(&a[end], &a[0]);DownAdjust(a, 0, end);end--;}
}

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

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

相关文章

React自定义Hook函数:高效组件开发的秘密武器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

LateX的基础学习

what can i say 在text.tex中写下 \documentclass{article} \begin{document]Hello \LaTeX. \end{document} 关闭记事本&#xff0c;cmd中dir保存&#xff0c;用latex text.tex来编译&#xff0c;可以命令行慢慢编译&#xff0c;这可以做成bat文件 为什么不直接开始在texst…

Meta提出全新文档级嵌入框架,利用LLM来增强信息检索能力

近年来&#xff0c;基于嵌入式检索&#xff08;embedding-based search&#xff09;或密集检索&#xff08;dense retrieval&#xff09;相比传统的稀疏检索&#xff08;sparse retrieval&#xff09;或基于词袋&#xff08;bag of words&#xff09;的方法&#xff0c;已经展示…

找不到msvcp140dll,无法继续执行代码的详细解决方法

在我们日常使用计算机进行各类工作任务的过程中&#xff0c;时常会遭遇一些突发的技术问题。比如&#xff0c;有时在运行某个重要程序或应用软件时&#xff0c;系统会突然弹出一个令人困扰的错误提示&#xff1a;“电脑提示找不到msvcp140.dll文件&#xff0c;因此无法继续执行…

多项式相关题()

D - S老师的虚树 值得一提的是如何求这个 a i a_i ai​&#xff0c;可以考虑按dfs序考虑同一种边&#xff0c;运用树状数组即可统计&#xff08;注意不要加重了&#xff0c;不需要打区间覆盖&#xff0c;这样可以不用打线段树&#xff09; F(i, 1, n) {ll sz d[i].size() - 1…

自动化测试的7个步骤

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

微服务:Eureka原理实践:@EnableEurekaServer、@LoadBalanced

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 微服务&#xff1a;Eureka原理实践&#xff1a…

国产生骨肉冻干品控好不好?热榜TOP5生骨肉冻干分享

对于新手养猫人来说&#xff0c;进口生骨肉冻干的高价常常让人疑惑&#xff0c;为何它能在养猫达人中赢得如此高的声誉&#xff1f;与国产生骨肉冻干相比&#xff0c;进口产品的价格高出数倍&#xff0c;那么这高昂的价格是否代表了其独特的价值&#xff0c;还是只是一个消费陷…

在React Router 6中使用useRouteLoaderData钩子获取自定义路由信息

在 React Router 6 中怎么像vueRouter一样&#xff0c;可以在配置路由的时候&#xff0c;定义路由的元信息(附加信息)&#xff1f;答案是可以的。稍有些复杂。核心是通过为每个路由定义了一个 loader 函数,用于返回自定义的路由信息&#xff0c;然后通过useRouteLoaderData 钩子…

力扣HOT100 - 94. 二叉树的中序遍历

解题思路&#xff1a; 递归 class Solution {List<Integer> list new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {recur(root);return list;}public void recur(TreeNode root) {if (root null) return;recur(root.left);lis…

最强开源大模型Meta LIama3抢先在线体验!

4月19日Facebook母公司Meta重磅推出了其迄今最强大的开源人工智能&#xff08;AI&#xff09;模型——Llama 3。模型分为两种规模&#xff1a;8B 和 70B 参数&#xff0c;每种规模都提供预训练基础版和指令调优版。最强开源大语言模型Meta LIama3可以在线体验啦&#xff01; G…

javaWeb宠物商店管理系统

摘 要 本系统是采用Java技术来构建的一个基于Web技术的B/S结构的宠物网站&#xff0c;该网站建立在Spring和Struts2框架之上&#xff0c;前台使用JSP作为开发语言&#xff0c;后台使用MySQL数据库管理系统对数据进行管理&#xff0c;开发环境选用MyEclipse&#xff0c;应用服务…