数据结构六:堆
创始人
2024-04-02 20:40:41
0

前言:上一篇我们讲了二叉树,你知道吗?堆的底层是一棵完全二叉树。这样说会不会就会觉得熟悉了。

目录

1.堆的概念及存储方式

 2:堆的创建

2.1:向下调整

3.堆的插入和删除

3.1:堆的插入

3.2:堆的删除

4.PriorityQueue的特性-----优先级队列

4.1常用接口介绍

4.1.1:优先级队列的构造

 4.1.2:插入/删除/获取

5:应用


1.堆的概念及存储方式

它的所有元素按照完全二叉树的顺序存储方式存储在一个一维数组中。

如果i为0,表示根节点。否则父亲节点:(i-1)/2

如果i*2+1小于节点个数。左孩子:2*i+1

如果i*2+2小于节点个数。右孩子:2*i+2

大堆:根节点比左右孩子都大。

小堆:根节点比左右孩子都小。

存储方式:堆是一颗完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。


 2:堆的创建

public class MyHeap {//它的存储结构是一维数组public int [] elem;public int usedSize;//记录数组中的有效元素个数public  static  final int DEFIND_SIZE=10;//数组容量//开辟数组空间public   void createHeap(){elem=new int [DEFIND_SIZE];}

2.1:向下调整

  public void CreateMinHeap(){for (int parent =(usedSize-1)/2 ; parent>=0; parent--) {shiftDown(parent,usedSize);//向下调整}}public  void shiftDown(int parent,int len){int child=parent*2+1;//必须有左孩子while(childelem[child]){//大于就交换swap(elem,parent,child);parent=child;child=parent*2+1;}else{//不大于break;}}
}
public void swap(int [] elem,int i,int j){int tmp=elem[i];elem[i]=elem[j];elem[j]=tmp;}
}

3.堆的插入和删除

3.1:堆的插入

堆的插入总共需要两个步骤

1.判断空间够不够,够就将元素放到底层空间中;不够,扩容

2.将最后新插的节点向上调整,知道堆的性质。

   //堆的插入public void offer(int val){//判断空间是否够if (isFull()){//满了,扩容//以二倍扩容elem= Arrays.copyOf(elem,elem.length*2);}//没有满elem[usedSize]=val;shiftUp(usedSize);usedSize++;//记录有效元素个数加加}//向上调整public void shiftUp(int child){//找到它的父亲int parent=(child-1)/2;while(parent>=0){if(elem[parent]>elem[child]){swap(elem,parent,child);child=parent;parent=(child-1)/2;}else{break;}}}public boolean isFull(){//如果有效元素个数等于大于数组长度//说明数组满了return  usedSize>=elem.length;}
}

3.2:堆的删除

注意:堆的删除一定时堆顶元素

1.将最后一个元素和堆顶元素交换。

2.将有效元素个数减减。

3.向下调整,符合堆的性质

 public int pop(){//判断堆是否为空if(isEmpty()){return -1;}//不为空,和最后一个元素交换位置int tmp=elem[0];swap(elem,0,usedSize-1);//有效元素减//向下调整shiftDown(0,usedSize-1);return tmp;}

4.PriorityQueue的特性-----优先级队列

优先级队列的底层是堆。

注意事项:

1.PriorueueQueue中放置的元素必须是能够比较大小,否则会抛出ClassCastException异常。

2.不能插入null对象.否则会抛出NullpointerException

3.没有容量限制,可以插入任意元素。

4.PriorityQueue默认情况是小堆


4.1常用接口介绍

4.1.1:优先级队列的构造


 4.1.2:插入/删除/获取

函数名功能介绍
boolean offer(E e)插入e,成功返回true.
E peek()获取优先级最高的元素,如果为空,返回null
int size()获取有效元素个数
E poll()移除优先级最高的元素并返回,如果为空,返回null
void clear()清空
boolean isEmpty()检查优先级队列是否为空,空返回null


扩容说明:

如果容量小于64是按照2倍方式扩容

如果容量大于64是按1.5倍方式扩容

如果容量大于最大值,按照最大值来进行扩容


5:应用

5.1:Top-k问题

1.用数据集合中前K个元素来建堆

1.1:前K个最大的元素,建小堆

1.2:前k个最小的元素,建大堆。

2。用剩下的元素依次和堆顶元素来比较,不满足则替换堆顶元素。

https://leetcode.cn/problems/smallest-k-lcci/

class Solution {public int[] smallestK(int[] arr, int k){//判断k是否大于1,数组是否为空if(arr.length==0||k<1){return  new int[0];}PriorityQueue p1=new PriorityQueue<>(k, new Comparator() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});//将前k个元素,建成大堆for (int i = 0; i arr[i]) {p1.poll();p1.offer(arr[i]);}}//将堆的元素赋值到数组里int [] ret=new int[k];for (int i = 0; i 

总结;

以上就是我总结的堆的知识点。若有错误,请各位铁铁留言纠错。若感觉不错,请一键三连。

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...