当前位置:网站首页>二叉堆的基础~
二叉堆的基础~
2022-08-11 04:00:00 【mmmenxj】
二叉堆:就是一颗完全二叉树
完全二叉树:满二叉树缺了一个右下角
堆的两个特点:
1.二叉堆首先是一颗完全二叉树(结构上)
2.二叉堆节点间关系满足以下关系:
堆中根节点的值>=子树中结点的值(最大堆/大根堆)
堆中根节点值<=子树中的结点值(最小堆/小根堆)
在大根堆中,只能保证当前根节点大于等于子树的所有节点,在任意子树中仍然满足
但是节点的大小关系和所处的层次无关。
完全二叉树(包括满二叉树)建议使用顺序表存储(数组)
完全二叉树中不存在只有右子树没有左子树的情况,不用存储空节点
其他二叉树不建议使用。
普通的二叉树不适用数组存储,就是因为要存储控几诶但,会浪费大量的空间。
如何仅用索引就能判断一个结点K是否有子树?
2k+1 <数组长度(因为满二叉树可以没有右子树)
给定一个结点k,如何判断他的父节点是否存在?
只需要看父结点的编号 > 0 即可
父节点的索引为 (k - 1) >> 1
向一个大根堆中添加一个元素,并且找到对应的位置:
public void add(int val){
data.add(val);
//进行元素的上浮操作
shiftUp(data.size() -1);
}
private void shiftUp(int k) {
//元素的上浮操作
//终止条件: 到达根节点 或者 当前结点值 <= 父节点值
while(k >0 && data.get(k) > data.get(parent(k))){
//未达到终止条件
//交换当前结点和父节点的值
swap(k,parent(k));
k = parent(k);
}
}
private void swap(int i, int j) {
int temp = data.get(i);
data.set(i,data.get(j));
data.set(j,data.get(i));
}将最大堆不断进行extractMax直到堆为空,我们可以得到一个降序排列的数组。
//取出当前最大队的最大值
public int extractMax(){
//取值注意判空
if(isEmpty()){
throw new NoSuchElementException("heap is empty cannot extract!");
}
//大根堆默认跟根节点元素最大
int max = data.get(0);
//1.将数组末尾元素顶到堆顶
int lastVal = data.get(data.size()- 1);
data.set(0,lastVal);
//2.将数组末尾的元素删除
data.remove(data.size() -1);
//3.进行元素的下沉操作
shiftDown(0);
return max;
}
private void shiftDown(int k) {
//还存在子树
while(leftChild(k) < data.size()){
int j = leftChild(k);
//判断是否有右树
if(j+1 < data.size() && data.get(j +1) >data.get(j)){
//此时右树存在,并且大于左树的值
j = j+1;
}
//此时j就对应左右子树的最大值
//和当前的k去比较
if(data.get(k) >data.get(j)){
//下沉结束
break;
}else{
swap(k,j);
k = j;
}
}
}测试数据时,理论上不能只使用一个小集合,我们使用ThreadLocalRandom生成一个10w数据的大集合,可以解决多个线程发生的竞争争夺。
这里列出我错误的原因:ThreadLocalRandom不能实例化new,直接使用它的静态方法current即可

从Math.random()改变到ThreadLocalRandom有如下好处:
我们不再有从多个线程访问同一个随机数生成器实例的争夺。
取代以前每个随机变量实例化一个随机数生成器实例,我们可以每个线程实例化一个。
heapify -- 堆化:将任意数组调整为堆结构
思路一(时间复杂度NlogN):
1.将任意数组看成一个完全二叉树
2.将这N个元素逐步调用add方法插入到一个新堆中,得到一个最大堆
int [] data = {15,17,19,13,22,16,28,30,41,62};
//逐步插入到堆中
MaxHeap heap = new MaxHeap();
for(int i :data){
heap.add(i);
//添加元素,其中包含了元素上浮
}
System.out.println(heap);shiftUp方法中,k = parent(k),除2操作,这就是二叉树的高度问题。
思路二(时间复杂度N):
1.让任意数组都可以看做一颗完全二叉树遍历
2.从当前这个完全二叉树的最后一个非叶子结点进行元素的下沉操作即可调整为堆
那么如何找到这个非叶子结点的呢?
最后一个叶子结点的双亲结点就是!
最后一个叶子结点 ---数组的最后一个元素
int lastNodeLeafNode = pareant(data.size() -1);
public MaxHeap(int[] arr){
data = new ArrayList<>(arr.length);
//先将arr的所有元素复制到data数组中
for(int i :arr){
data.add(i);
}
//从最后一个非叶子节点开始进行shiftDown
for (int i = parent(data.size() -1); i >= 0 ; i--) {
shiftDown(i);
}
}边栏推荐
- Echart地图的省级,以及所有地市级下载与使用
- leetCode刷题14天二叉树系列之《 110 平衡二叉树判断》
- 【FPGA】day22-SPI协议回环
- console.log alternatives you didn't know about
- Multi-serial port RS485 industrial gateway BL110
- CTO said that the number of rows in a MySQL table should not exceed 2000w, why?
- Interchangeability and Measurement Techniques - Tolerance Principles and Selection Methods
- How to rebuild after pathman_config and pathman_config_params are deleted?
- 使用百度EasyDL实现森林火灾预警识别
- MYSQLg高级------聚簇索引和非聚簇索引
猜你喜欢

Clang Code Model: Error: The clangbackend executable “X:/clangbackend.exe“ could not be started

Kubernetes集群搭建Zabbix监控平台

【FPGA】day18-ds18b20实现温度采集

【Yugong Series】August 2022 Go Teaching Course 036-Type Assertion

【力扣】22.括号生成

UNI-APP_iphone bottom safe area

Qnet Weak Network Test Tool Operation Guide

Multi-serial port RS485 industrial gateway BL110

leetCode刷题14天二叉树系列之《 110 平衡二叉树判断》

【FPGA】名词缩写
随机推荐
[FPGA] day19- binary to decimal (BCD code)
App基本框架搭建丨日志管理 - KLog
Which one to choose for mobile map development?
Differences and connections between distributed and clustered
一文读懂 高性能可预期数据中心网络
这些云自动化测试工具值得拥有
洛谷P7441 Erinnerung
LeetCode814 Math Question Day 15 Binary Tree Series Value "814 Binary Tree Pruning"
CTO said that the number of rows in a MySQL table should not exceed 2000w, why?
What are port 80 and port 443?What's the difference?
【FPGA】day22-SPI协议回环
C语言 recv()函数、recvfrom()函数、recvmsg()函数
机器学习是什么?详解机器学习概念
console.log alternatives you didn't know about
我的 archinstall 使用手册
MySQL数据库存储引擎以及数据库的创建、修改与删除
洛谷P4324 扭动的回文串
北湖区燕泉街道开展“戴头盔·保安全”送头盔活动
es-head插件插入查询以及条件查询(五)
What has programmatic trading changed?