二叉树之堆树

devtools/2024/9/29 16:57:45/

堆树是一种完全二叉树,完全二叉树特点:除了最后一层所有层都填满,最后一层节点从左到右排列。堆树分为两种类型:大顶堆和小顶堆。

大顶堆:每个节点的值都大于或等于其子节点的值,根节点是最大值。

小顶堆:每个节点的值都小于或等于其子节点的值,根节点是最小值。
在这里插入图片描述

堆的存储

由于堆是一个完全二叉树,根据完全二叉树的特点,可以使用数组存储堆树。

在这里插入图片描述

如上小顶堆。数组下标x对应的左子节点下标为x*2,右子节点元素下标为x乘2+1,其父节点下标为x/2。

如元素15其下标为3,则左子元素31的下标为6,右子元素61下标为7。父节点下标为1。

堆的构建

往堆上添加一个元素需要继续满足堆的特点,这就需要进行元素调整交换,这个过程就叫做堆化。

堆化有两种方式:

向上堆化:新插入一个节点后,比较该节点与其父节点的值,如果不符合堆的性质,则交换,继续向上堆化,直到满足堆的性质。

向下堆化:从某个节点开始,比较该节点与其子节点的值,如果不符合堆的性质(例如在最大堆中,父节点小于子节点),则交换节点和最大的子节点,继续向下堆化直到满足堆的性质。

元素的插入

这里以大顶堆构建为例来代码演示

先定义堆基本结构

java">    int[] data; //数组存储堆int capacity; //容量int size;//当前堆中元素数public MaxHeapTree(int capacity){data = new int[capacity+1];this.capacity = capacity;this.size = 0;}

向上堆化插入元素

java">    public void insertBottom(int val){if(size >= capacity) return;data[++size] = val;int current = size; //当前节点下标int parent = current/2;//父节点下标//判断当前节点是否大于父节点while (parent > 0  && (data[current] > data[parent]) ){//当前节点和父节点交换int tmp = data[current];data[current] = data[parent];data[parent] = tmp;current = parent;parent = current/2;}}

向上堆化需要将新插入的元素放到堆最后。代码还是比较简单的。

插入数据测试

java">        MaxHeapTree heap = new MaxHeapTree(10);int[] arr = {8,6,5,9,4,27,22,55,3,88};for (int i = 0; i < arr.length; i++) {heap.insertBottom(arr[i]);}System.out.println(Arrays.toString(heap.data));

最后输出内容:[0, 88, 55, 22, 8, 27, 5, 9, 6, 3, 4] 满足大顶堆的特点。

删除堆顶元素

如果将堆顶元素取出,这里也就是取最大数。剩下的数则需要调整用来继续满足堆的特点。如果直接将堆顶元素的左右子节点提升到根节点,进行向下堆化,最后可能导致堆数不满足完全二叉树的特点。

所以这里堆顶元素删除后一般将最后一个元素拿到堆顶位置,然后进行向下堆化。这样堆化完成后的结构很顶还是完全二叉树,因为堆化过程中只进行节点的交换。

来看下具体代码

java">    public int removeTop(){if(size == 0) return -1;int val = data[1];data[1] = data[size];heapfiyUp(1);return val;}public void heapfiyUp(int index,int total){while (true){int max = index;int left = index*2; //左子int right = left +1; //右子//找到当前节点和其两个字节点中最大的if(left <= total && data[left] > data[max]) max = left;if(right <= total && data[right] > data[max]) max = right;//如果最大是当前元素,不用交换继续比较了if(max == index) break;//否则交换当前元素和最大元素位置swap(index,max);//将当前元素切换到最大元素,继续比较index = max;}}

这样从堆顶元素不断取最大元素,就可以获取整个堆中topK的值。heapfiyUp方法就是从上往下进行堆化,入参就是当前要进行堆化的节点位置。

堆排序

对于堆排序只要理解了堆化的两个方法排序就变得简单了。

首先要将排序的数组进行堆化,堆化这里按上面有两种方法,向上堆化,这个是从前往后每个元素一次插入到堆中。而对于向下堆化,由于每次都是和自己子节点进行比较,由于所有的叶子节点都没有子节点,所以叶子节点不需要进行向下堆化的过程,从第一个非叶子节点进行堆化即可。由于堆数是一个完全二叉树,最后一个叶子节点是 节点数/2。所以只需要进行 节点数/2次就可以构建完成堆。

堆构建完成后,元素不是完全有序的,例如上面的例子构建完成后是[0, 88, 55, 22, 8, 27, 5, 9, 6, 3, 4]。这里只能保证一点堆顶是最大的。

排序只需要每次将堆顶元素拿出和数组最后一个元素进行交换,然后剩下的n-1个元素在进行一次向下堆化又找到了剩下的n-1个中最大的,重复上面的过程最后就完成了数组的排序。

代码如下:

java">    public void sort(){int n = size;//堆容量while(n > 1){swap(1,n);//将堆顶元素和最后一个元素交换heapfiyUp(1,--n); //从堆顶进行向下堆化}}

这里省略建堆的过程。

堆通常用于实现优先队列,快速找到极值。和topK问题,topK一般建立小顶对,然后每次和堆顶元素比较即可。


http://www.ppmy.cn/devtools/118786.html

相关文章

ACM第三次考核题解

ACM第三次考核题解 题目序号难度题目编号题目考察知识点1签到题A这是一道很难的题&#xff01;&#xff01;&#xff01;输出2迷之难度F神说要有光&#xff0c;于是有了手电筒贪心3简单BThis is a real English problem&#xff01;思维 英语4简单C玩具简单排序5简单I“近义词…

Python库matplotlib之二

Python库matplotlib之二 figureAxessubplot figure matplotlib.pyplot.figure(numNone, figsizeNone, dpiNone, facecolorNone, edgecolorNone, frameonTrue, FigureClass<class ‘matplotlib.figure.Figure’>, clearFalse, **kwargs) num&#xff0c;int 或 str 或 fi…

ECCV 2024 | 融合跨模态先验与扩散模型,快手处理大模型让视频画面更清晰!

计算机视觉领域顶级会议 European Conference on Computer Vision&#xff08;ECCV 2024&#xff09;将于9月29日至10月4日在意大利米兰召开&#xff0c;快手音视频技术部联合清华大学所发表的题为《XPSR: Cross-modal Priors for Diffusion-based Image Super-Resolution》——…

JAVA秘密花园匿名情侣假装恋爱体验系统小程序源码

秘密花园&#xff1a;匿名情侣假装恋爱体验系统&#xff0c;解锁爱情新奇遇&#x1f339; &#x1f33f; 开篇&#xff1a;踏入未知的爱情秘境 在繁忙的都市生活中&#xff0c;你是否渴望一场不期而遇的浪漫&#xff1f;是否想尝试一段没有负担、纯粹美好的恋爱体验&#xff…

kafka发送消费核心参数与设计原理详解

核心参数详解: 发送端参数: 发送方式:默认值一般都是1: 重试参数 : 批量参数: 消费端参数: 自动提交参数: 如果是false,就是说消费完后不提交位移。也就是说比如之前消费的1-5.第N次还是消费到1-5.如果是false。那么第一次消费1-3,第二次消费4-5:默认是true:我们…

Flink CDC

全增量一体化架构 自 2.0 版本起&#xff0c;Flink CDC 引入了增量快照框架&#xff0c;实现了数据库全量和增量数据的一体化读取&#xff0c;并可以在全量和增量读取之间进行无缝切换。在读取全量数据时&#xff0c;Flink CDC source 会首先将数据表中的已有数据根据主键分布切…

Oracle(145)如何进行数据库的日常维护?

数据库的日常维护是确保数据库性能稳定、数据安全可靠的关键。以下是进行数据库日常维护的几个重要步骤&#xff0c;包括示例代码&#xff0c;适用于大多数关系型数据库系统&#xff0c;如Oracle, MySQL, PostgreSQL等。 1. 监控数据库性能 监控数据库性能可以帮助及时发现和…

【Python快速学习笔记02】基础语法学习(变量等)

目录 1.标识符与代码书写注意点 2.变量类型 1.标识符与代码书写注意点 &#xff08;1&#xff09;组成&#xff1a;字母&#xff0c;下划线&#xff0c;数字 &#xff08;2&#xff09;注意点&#xff1a;但是不能由数字开头&#xff0c;区分大小写 &#xff08;3&#xff…