转载请注明源出处: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. Django入门与实践 17-26章总结

    Django入门与实践-第17章:保护视图 Django 有一个内置的视图装饰器 来避免它被未登录的用户访问: 现在如果用户没有登录,将被重定向到登录页面: 现在尝试登录,登录成功后,应用程序会跳转到 ...

  2. 自学如何去学习jQuery

    学习JQ第一个demo: 制作一个轮播图,制作方法我前面写了一篇博客,传送门-->http://www.cnblogs.com/yewenxiang/p/6100206.html 需要的JQ知识 ...

  3. php mysql增删查改

    php mysql增删查改代码段 $conn=mysql_connect('localhost','root','root');  //连接数据库代码 mysql_query("set na ...

  4. VS2010程序打包操作--超详细

    1.  在vs2010 选择“新建项目”----“其他项目类型”----“Visual Studio Installerà“安装项目”: 命名为:Setup1 . 这是在VS2010中将有三个文件夹, ...

  5. (线段树)Balanced Lineup --POJ --3264

    链接: 对于POJ老是爆,我也是醉了, 链接等等再发吧! http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82832#problem/G 只 ...

  6. hdu 5020 求3点共线的组合数

    http://acm.hdu.edu.cn/showproblem.php?pid=5020 求3点共线的组合数 极角排序然后组合数相加 #include <cstdio> #includ ...

  7. 【WinRT】使用 T4 模板简化字符串的本地化

    在 WinRT 中,对控件.甚至图片资源的本地化都是极其方便的,之前我在博客中也介绍过如何本地化应用名称:http://www.cnblogs.com/h82258652/p/4292157.html ...

  8. C++ - explicit和volatile/const的内容

    第一眼见到explicit和volatile可能会一愣一愣的觉得可能是c11或者c14新加的标识符. 其实不是这样,volatile和const两个关键字在C语言的第二个版本KR C的时候就被加入了C ...

  9. HTTP响应状态码说明

    当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(Server Header)用以响应浏览器的请求. HTTP状态码共分为五种类型: 1**:信息,服务器接收到请求,需 ...

  10. go语言最快最好运用最广的web框架比较(大多数人不了解的特性)

    令人敬畏的Web框架 如果你为自己设计一个小应用程序,你可能不需要一个Web框架,但如果你正在进行生产,那么你肯定需要一个,一个好的应用程序. 虽然您认为自己拥有必要的知识和经验,但您是否愿意自行编写 ...