转载请注明源出处:http://www.cnblogs.com/lighten/p/7299233.html

1.前言

  本章介绍队列中的PriorityQueue--优先队列,顾名思义,这是一个可以指定特定排序的队列。有些违背队列的先入先出,但是其是按照有序的出队列,也是一个比较实用的类。

2.PriorityQueue

  PriorityQueue继承自抽象父类AbstractQueue,其数据结构依旧保持简单:

  一个数组队列,一个大小,一个排序规则的比较器。如果比较器为null的时候,就按照元素自身的compareTo方法进行比较排序。这个队列和之前容器又在初始化的大小和扩容大小上不一致,其默认大小为11,大小小于64的时候扩容后为原来的3倍,大于64的时候,扩容后打下是原来的2倍。

  PriorityQueue的add(E)方法和offer(E)方法是一样的。

  先判断容量大小,再判断是否是第一个,最后进行排序。

  这个排序看过去有些奇怪,怎么有parent,并且下标是(k-1)>>>1呢?其实这里的操作就反应了优先队列的真正数据结构,其实际上是一个二叉树,将二叉树存储在数组之中而已。根节点就是数组的0位。下图给出其具体结构:

  上图就是随手画的一个二叉树,下面是对应的二叉树的数组中的位置。二叉树存入数组的方式很简单,就是从上到下,从左到右。PriorityQueue的是一个有特点的完全二叉树,且不允许出现null节点,其父节点都比叶子节点小,这个是堆排序中的小顶堆。如果按数组顺序我们可以得到如下结论:

    左叶子节点=父节点下标*2+1

    右叶子节点=父节点下标*2+2

    父节点=(叶子节点-1)/2

  插入节点也就比较好处理了,和父节点比较,大于父节点的就不动,小于父节点的就上浮,这就是siftUp方法的作用了。顺便一提,最小堆并不保证左右节点的大小关系,只关心父节点和子节点的关系。

  由上面的叙述,不难看出优先队列如果不进行调整,是无法保证优先顺序的,子节点大小是无序的。所以每次出队列的都是根元素,根元素肯定是最小的。移除了一个元素后,树的结构势必会被破坏,所以每次的移除操作都会调整树,保证其符合定义。

  siftDown就是用于做这样的调整的,其具体实现如下:

  看代码就可以知道,其移除节点之后,是判断了左右节点小的那个进行上浮的,而后循环上浮。

  移除任意一个位置的内容时,其是将最后一个元素取出来变成null了。然后调用siftDown,重新找到最后一个元素应该去的位置,其它元素填补移除位。一般而言这样就应该足够了,但是在某些情况下还需要进行后面的元素与前面进行交换。就像代码中所表现的一样,最后一个元素正好填补的是移除的那个空缺,此种情况下并不能说明该结构是正确的,造成这种现象的原因就在于优先队列并不保证左右的大小顺序,看下图就能很好理解问题所在,并且此种情况需要进行siftUp(),当发生这种异常的情况,才会返回这个异常值,其它时候都是返回null.

3.示意图

  移除任意位置的图就不再给出了,2小结结尾已经进行过说明,先进行一次siftDown,再进行一次siftUp。

4.其它参考文章

  http://www.cnblogs.com/CarpenterLee/p/5488070.html

Java之集合(六)PriorityQueue的更多相关文章

  1. Java学习第六篇:集合类

    一.Java集合类框架 Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合:从Java5以后,J ...

  2. 【Java】集合_学习笔记

    一.集合 1.集合类也称容器类,主要负责保存.盛装其他数据. 2.集合可以保存数量不确定的数据,保存具有映射关系的数据(也称关联数组). 3.Java5后提供一些多线程安全的集合类,放在java.ut ...

  3. Java学习-集合(转)

    在编写java程序中,我们最常用的除了八种基本数据类型,String对象外还有一个集合类,在我们的的程序中到处充斥着集合类的身影!java中集合大家族的成员实在是太丰富了,有常用的ArrayList. ...

  4. 浅谈Java的集合框架

    浅谈Java的集合框架 一.    初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...

  5. java的集合框架set 和map的深入理解

    Java的集合框架之Map的用法详解 Map有两种比较常用的实现:HashMap 和 TreeMap. HashMap: HashMap 也是无序的,也是按照哈希编码来排序的,允许使用null 值和n ...

  6. Java面试集合(七)

    前言: Java面试集合(六) 的回顾,对于final可以修饰常量,方法,和类,一旦常量定义好后就不可改变,而方法,用final来修饰方法,方法不可重载,继承,重写,final用来修饰类,该类不能被继 ...

  7. Java面试集合(三)

    前言 大家好,给大家带来Java面试集合(三)的概述,希望你们喜欢 三 1.在Java中是否可以含有多个类? 答:可以含有多个类,但只有一个是public类,public类的类名与文件名必须一致. 2 ...

  8. 算法篇(前序)——Java的集合

    菜鸟拙见,望请纠正:附上JDK参考文档(中文文档和英文文档):链接:https://pan.baidu.com/s/14KDmCtQxeGCViq7e0zENjA 密码:e9xs  以及算法篇全文链接 ...

  9. Java基础-集合的嵌套

    Java基础-集合的嵌套 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.静态导入 静态导入是在JDK1.5后的新特性,可以减少开发的代码量,但是实际用处是很一般,静态导入的标准 ...

随机推荐

  1. C++ 动态分配 和 内存分配和内存释放

    动态分配 动态分配可以说是指针的关键所在.不需要通过定义变量,就可以将指针指向分配的内存.也许这个概念看起来比较模糊,但是确实比较简单.下面的代码示范如何为一个整数分配内存: int *pNumber ...

  2. CentOS yum 源的配置与使用(引用)

    http://www.cnblogs.com/mchina/archive/2013/01/04/2842275.html

  3. Tcl写法

    #=============================================================== #Analysi&Synthesis execute_modu ...

  4. python与JavaScript中正则表达式如何转换

    使用python爬取网站数据的时候,总会遇到各种各样的反爬虫策略,有很大一部分都和JavaScript(以下简称为JS) 有关.在破解这些JS代码的过程中,经常会遇到模拟JS正则表达式的情况,因此,今 ...

  5. crosss compile VLC with OpenMAX on ARM board(RockChip RK3399),in order to use Hard Acceleration when decode video

    reference:http://www.x90x90x90.com/en/raspberry-pi-3-howto-compile-vlc-with-hardware-acceleration/ 1 ...

  6. html5 录制/保存视频/录音

    国内这方面的资料真少的可怜,翻出去一搜一大把,推荐一个github的插件库,非常强大,支持各种各样的录制方式. 下载完成之后,引用对应的js立即可以使用. <script src="R ...

  7. D3_book 7 area

    <!-- area的例子csv使用node.js提供的 --> <!DOCTYPE html> <meta charset="utf-8"> & ...

  8. Redis.conf配置文件内容详解

    #默认以后台方式运行 daemonize yes #指定redis pid文件 pidfile /data/apps/var/redis2/redis2.pid #指定redis启动占用的端口 por ...

  9. 玩了下STM8单片机

    偶然的机会,发现STM8真是又便宜又好用啊,哈哈! 买了一个STM8S103F3的小板子,再加一个ST-Link调试器,总共才35块钱!对于我们这种玩习惯了动辄上千上万的FPGA开发板的人来说,就是白 ...

  10. /bin/sh: cc: 未找到命令

    redis 4安装出现 /bin/sh  cc:  未找到命令 解决: yum -y install gcc automake autoconf libtool make