数据结构六:堆
创始人
2024-04-02 12:48:12
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 

总结;

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

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...