优先级队列(堆)

news/2023/6/8 0:31:55

目录

  • 一、堆的概念以及堆的创建
    • 1.堆的概念
  • 二.堆的创建
    • 2.1向下遍历
    • 2.2建堆操作
  • 三. 堆方法的构建
    • 3.1 入队列操作
    • 3.2出队列操作
    • 3.3查看头元素
  • 四.优先级队列(堆)方法的使用
    • 4.1堆的初始化(大堆和小堆创建)
  • 五.堆排序(大堆)

一、堆的概念以及堆的创建

1.堆的概念

    什么是堆?(堆的逻辑上是一个完全二叉树,实际上是保存在数组中)

    我们把一个完全二叉树通过层序遍历存储到数组当中,这个数组就叫做堆。

在这里插入图片描述
在这里插入图片描述

     注意:堆中的元素不能为空.(浪费大量空间)

     什么是大根堆和小根堆?

    大根堆是指根结点的关键字是堆里所有结点关键字中最大者
在这里插入图片描述

    小根堆:根结点的值是所有结点值中最小者.

在这里插入图片描述

    父亲结点为i时,左孩子的结点为 i* 2+1,右孩子的结点为 * 2+2;孩子结点为i时,父亲结点为(i-1)/2.

二.堆的创建

2.1向下遍历

    对于堆中的排序我们可以采用向下遍历的方法,我们就拿小堆的向下遍历来做例子.
在这里插入图片描述

2.2建堆操作

    由于堆的底层是数组,我们开始要创建一个数组并且初始化

public class TestHeap {public int[] elem;public int uesdSize;public TestHeap(){this.elem=new int[10];}
}

    接下来我们要将一段无序的数组放进去,并且通过elem数组拷贝进来,同时我们通过由下向上不断遍历由上向下的函数

    public void createBigHeap(int[] array){for(int i=0;i<array.length;i++){this.elem[i]=array[i];this.usedSize++;}for(int i=(this.usedSize-1-1)/2;i>=0;i--){shiftDown(i);}}

    接下来我们编写由上向下的函数shiftDown(i);

    public void shiftDown(int parent){int child=parent*2+1;while (child<this.usedSize){if(child+1<this.usedSize && this.elem[child+1]<this.elem[child]){child++;}if(this.elem[parent]>this.elem[child]){int temp=this.elem[parent];this.elem[child]=this.elem[parent];this.elem[parent]=temp;parent=child;child=child*2+1;}else {break;}}}

    注意:一般来说for循环的时间复杂度为N,shiftDown的时间复杂度为logN,所以为O(N*logN),但是实际上为O(N);

三. 堆方法的构建

3.1 入队列操作

    对于入队列操作我们采用向上遍历的方法。

在这里插入图片描述

    我们入队列时,先判断是否满了,然后我们将入队列的值放入数组的最后一个,将它和他的父亲节点进行比较,若小于进行交换,一直循环到父亲节点小于0;

 public boolean isFull(){return this.elem.length==this.usedSize;}public void push(int val){if(isFull()){this.elem=Arrays.copyOf(this.elem,2*this.elem.length);}this.elem[this.usedSize]=val;this.usedSize++;shiftUp(this.usedSize-1);}public void shiftUp(int child){int parent=(child-1)/2;while (parent>=0){if(this.elem[parent]>this.elem[child]){int temp=this.elem[parent];this.elem[parent]=this.elem[child];this.elem[child]=temp;child=parent;parent=(parent-1)/2;}else{break;}}}

3.2出队列操作

    对于出队列的操作时,我们先让头和尾互换,然后将头向下遍历就行了.

    public int pop(){if(isEmpty()){throw new RuntimeException("为空不能取出");}int temp=this.elem[0];this.elem[0]=this.elem[this.usedSize-1];this.elem[this.usedSize-1]=temp;this.usedSize--;shiftDown(0);return temp;}public boolean isEmpty(){return this.usedSize==0;}

3.3查看头元素

    public boolean isEmpty(){return this.usedSize==0;}   public int peek(){if(isEmpty()){throw new RuntimeException("为空不能取出");}return this.elem[0];}

四.优先级队列(堆)方法的使用

    PriorityQueue是优先级队列
下面的它的方法和使用:

    public static void main(String[] args) {PriorityQueue<Integer> pq=new PriorityQueue<>();pq.offer(1);pq.offer(2);pq.offer(3);System.out.println(pq.poll());System.out.println(pq.poll());System.out.println(pq.poll());//1   2   3}

4.1堆的初始化(大堆和小堆创建)

    对于大堆和小堆的创建我们需要重写Comparator方法来进行操作.

    我们使用匿名内部类进行编写详细方法如下

小堆:PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1-o2;}});大堆:PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});

五.堆排序(大堆)

在这里插入图片描述

    我们先将数组变成大堆,然后将第一个数和最后一个数进行交换,这时将最大的一个数就确定下来了,固定这个数,将第一个数进行排序,重复上述过程.

代码实现:

//堆排序public void heapSory(){int end=this.usedSize-1;while (end>0){int temp=this.elem[0];this.elem[0]=this.elem[end];this.elem[end]=temp;shiftDown01(0,end);end--;}}public void shiftDown01(int parent,int k){int child=parent*2+1;while (child<k){if(child+1<k && this.elem[child+1]>this.elem[child]){child++;}if(this.elem[child]>this.elem[parent]){int temp=this.elem[child];this.elem[child]=this.elem[parent];this.elem[parent]=temp;parent=child;child=child*2+1;}else{break;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4566161.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

手机QQ垃圾文件清理。

最近手机存储空间不足&#xff0c;发现经常使用的QQ号累积的垃圾文件太多了&#xff0c;记录下&#xff1a;

FS2111单节锂电池升降压稳压输出3.3V200MA静态电流10UA

单节锂电池供电需要输出3.3V可采用FS2111升压输出5VFS6206A33A低功耗超速线性稳压LDO输出3.3V 200MA&#xff0c;FS2111升压电路 ​ FS6206A33A稳压LDO电路 FS2111​单节锂电池升降压稳压输出3.3V200MA静态电流10UA 概述 FS2111是一款具有仅 6uA 静态电流 的同步升压变换器。…

mos管实现主副电源自动切换电路,并且“零”压降,静态电流20uA

在国外看到一个电路&#xff0c;也是写主副电源自动切换的电路&#xff0c;设计的非常巧妙。 上面电路设计也挺不错的&#xff0c;如果VCC端需要的电压不一定要求等于VUSB&#xff0c;那么这个电路是可以的&#xff0c;那么问题来了&#xff0c;如果主副输入电压相等&#xff0…

京东接入数字人民币系统,超100万用户使用数字人民币消费

数字人民币&#xff0c;字母缩写按照国际使用惯例暂定为“e-CNY”&#xff0c;是由中国人民银行发行的数字形式的法定货币。 1月4日&#xff0c;数字人民币&#xff08;试点版&#xff09;App在安卓各大应用商店、iOS App Store正式上线&#xff0c;并在App Store财务类应用榜上…

vue3中的v-for

一.列表渲染v-for 真实开发中&#xff0c;往往会从服务器中拿到一组数据&#xff0c;并且需要对其进行渲染&#xff0c;这个时候可以使用v-for完成。 1.v-for的基本使用 1&#xff09;基本格式&#xff1a;“item in 数组” 数组通常是来自data或者prop&#xff0c;也可以是…

人民币中文大写字符转成阿拉伯数字工具类

最近开发的项目&#xff0c;处理数据过程中有一需求就是根据人民币中文大写转换成阿拉伯数字&#xff1b;于是马上百度查找前辈们贡献的资源&#xff0c;发现很少涉及&#xff0c;大部分都是阿拉伯数字转换成中文。于是只能自己敲代码&#xff0c;经过测试已满足项目需求&#…

金融帝国2(Capitalism.Lab)完美破解修复版下载

重大消息&#xff1a;《金融帝国2》(Capitalism 2: Capitalism Lab)自动存档BUG已经完美修复 金融帝国2(Capitalism.Lab)完美破解修复版下载中文名称: 金融帝国2&#xff1a;金融帝国实验室英文名称: Capitalism 2: Capitalism Lab游戏类型: SLG 策略游戏资源格式: 光盘镜像版本…

『默哀』你的梦或许因为这个新闻而碎了【用你的程序语言 抛出一行异常】

对很多程序猿而言&#xff1a; 提升技术&#xff0c;构思产品&#xff0c;熬夜编码&#xff0c;拉到风投&#xff0c;艰苦创业&#xff0c;做大公司 —— 这是很多程序猿的梦想。 2017-09-09最新新闻 —— 你的梦或许碎了&#xff1a; 《传WePhone创始人自杀&#xff0c;去世…