网站建站与优化网站编辑岗位
news/
2025/9/23 14:13:00/
文章来源:
网站建站与优化,网站编辑岗位,医院做网站需要多少钱,阿里云 wordpress主机名堆的概念
堆是一棵完全二叉树#xff0c;一般使用数组来存储。通俗来讲堆其实就是利用数组来维护一个完全二叉树。
按照堆的特点可以把堆分为大顶堆和小顶堆 大顶堆#xff1a;堆的每个结点的值都大于或等于其左右孩子结点的值 小顶堆#xff1a;堆的每个结点的值都小于或…堆的概念
堆是一棵完全二叉树一般使用数组来存储。通俗来讲堆其实就是利用数组来维护一个完全二叉树。
按照堆的特点可以把堆分为大顶堆和小顶堆 大顶堆堆的每个结点的值都大于或等于其左右孩子结点的值 小顶堆堆的每个结点的值都小于或等于其左右孩子结点的值
根据堆的概念利用数组维护的完全二叉树可以推导出 假设 节点A 在数组 tree 的索引为 i 则
1A节点的左节点索引leftIdx (i1)*2 -1 2A节点的右节点索引rightIdx (i1)*2 3A的父节点索引parentIdx (i-1)/2
堆的构建
堆的构建可以看成是空堆中逐渐插入数据因此构建堆应该先实现堆的插入方法。
往堆中插入节点
往堆中插入数据时可能会破坏大顶堆或小顶堆根节点大于左右节点的性质因此需要做出调整。
堆的插入流程如下
将插入的数组置于数组的尾部从尾部开始比较当前节点一开始为插入的节点与父节点是否满足大顶堆或小顶堆的性质不满足则交换父子节点。重复2步骤直到满足大顶堆性质或到达堆顶
示例代码 /*** 插入的流程* 1.先把元素放到数组最后* 2.与父元素比较若父元素小于子元素则交换父子元素直到父元素大于等于子元素* param n*/public void add(int n){if(sizecapacity){throw new RuntimeException(堆达到最大容量);}//新节点的索引int curIdx size;//将新节点插入数组尾部table[curIdx] n;//获得父节点索引具体代码在参考后文的完整示例//父节点索引 pIdx (curIdx-1)/2int pIdx getParent(curIdx);/*** 调整堆使其符合大顶堆的性质时间复杂度O(logn)* 与父元素比较若父元素小于子元素则交换父子元素直到父元素大于等于子元素*/while(table[curIdx]table[pIdx]){//子节点值大于父节点交换父子节点int t table[pIdx];table[pIdx] table[curIdx];table[curIdx] t;curIdx pIdx;pIdx getParent(curIdx);}size;}在清楚堆的插入过程之后堆的构建就是直接调用插入方法往堆中存放数据。
同时由上述可知往堆中添加元素的时间复杂度为 O(logN)因此构建堆的时间复杂度为n次插入即 O(NlogN)
删除堆顶节点
删除堆顶元素的流程
用堆的最后一个元素数组中的最后一个元素代替堆顶元素数组的第一个元素判断当前元素一开始为堆顶是否小于左右子元素小于则用左右子元素中较大的元素和当前元素进行交换重复步骤2直接节点大于左右元素或没有左右元素
示例代码
/*** 删除并返回堆顶元素* 删除流程* 1.把最后一个元素代替删除位置的元素* 2.与子元素比较把较大的子元素与当前元素交换直到当前元素大于左右子元素* return 堆顶元素*/public int remove(){//待删除的堆顶元素int v table[0];//用堆的最后一个元素数组中的最后一个元素代替堆顶元素数组的第一个元素table[0] table[size-1];size--;//调正堆使堆满足大顶堆的性质//当前元素索引一开始为堆顶元素int curIdx 0;while(true){//获得当前元素的左右节点索引具体代码参考后面完整示例int lf getLeftChild(curIdx);int rt getRightChild(curIdx);if(lf-1rt-1){//没有左右元素无需调整break;}//较大的子元素索引int swapIdx;if(lf-1||rt-1){swapIdx lf-1?rt:lf;}else{swapIdx table[rt]table[lf]?rt:lf;}if(table[curIdx]table[swapIdx]){//父元素大于左右子元素结束交换break;}//用较大的子元素代替父元素int t table[curIdx];table[curIdx] table[swapIdx];table[swapIdx] t;curIdx swapIdx;}//返回被删除的元素return v;}完整代码
/*** author Darren* date 2021/6/24 15:54* 简单大顶堆的实现*/
public class Heap {//堆的容量int capacity;//已存放的节点数int size;//存放完全二叉树结构的数组int[] table;Heap(int capacity){this.capacity capacity;table new int[capacity];}/*** 插入的流程* 1.先把元素放到数组最后* 2.与父元素比较若父元素小于子元素则交换父子元素直到父元素大于等于子元素* param n*/public void add(int n){if(sizecapacity){throw new RuntimeException(堆达到最大容量);}//当前元素的索引int curIdx size;//将新节点插入数组尾部table[curIdx] n;int pIdx getParent(curIdx);/*** 调整堆使其符合大顶堆的性质时间复杂度O(logn)* 与父元素比较若父元素小于子元素则交换父子元素直到父元素大于等于子元素*/while(table[curIdx]table[pIdx]){int t table[pIdx];table[pIdx] table[curIdx];table[curIdx] t;curIdx pIdx;pIdx getParent(curIdx);}size;}/*** 删除堆顶元素* 删除流程* 1.把最后一个元素代替删除位置的元素* 2.与子元素比较把较大的子元素与当前元素交换直到当前元素大于左右子元素* return*/public int remove(){//待删除的堆顶元素int v table[0];//用堆的最后一个元素数组中的最后一个元素代替堆顶元素数组的第一个元素table[0] table[size-1];size--;//调正堆使堆满足大顶堆的性质//当前元素索引一开始为堆顶元素int curIdx 0;while(true){int lf getLeftChild(curIdx);int rt getRightChild(curIdx);if(lf-1rt-1){//没有左右元素无需调整break;}//较大的子元素索引int swapIdx;if(lf-1||rt-1){swapIdx lf-1?rt:lf;}else{swapIdx table[rt]table[lf]?rt:lf;}if(table[curIdx]table[swapIdx]){//父元素大于左右子元素结束交换break;}//用较大的子元素代替父元素int t table[curIdx];table[curIdx] table[swapIdx];table[swapIdx] t;curIdx swapIdx;}return v;}public int getLeftChild(int i){int index (i1)*2-1;//indexsize 说明没有左子节点return indexsize?index:-1;}public int getRightChild(int i){int index (i1)*2;//indexsize 说明没有右子节点return indexsize?index:-1;}public int getParent(int i){return (i-1)/2;}
}参考 推荐堆排序大顶堆、小顶堆----C语言 排序六 堆排序 数据结构堆Heap
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/912795.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!