转载请注明原创地址http://www.cnblogs.com/dongxiao-yang/p/6293807.html

java.util.concurrent.PriorityBlockingQueue内部用二叉堆实现了一个优先队列,所有插入的元素必须实现java.lang.Comparable接口。由于完全二叉树可以用数组来表示,所以队列内部元素存放在可变长度数组queue里。

private transient Object[] queue; //用于存放元素的数组

一 插入元素入队

  1. public boolean offer(E e) {
  2. if (e == null)
  3. throw new NullPointerException();
  4. final ReentrantLock lock = this.lock;
  5. lock.lock();
  6. int n, cap;
  7. Object[] array;
  8. while ((n = size) >= (cap = (array = queue).length))
  9. tryGrow(array, cap);
  10. try {
  11. Comparator<? super E> cmp = comparator;
  12. if (cmp == null)
  13. siftUpComparable(n, e, array);
  14. else
  15. siftUpUsingComparator(n, e, array, cmp);
  16. size = n + 1;
  17. notEmpty.signal();
  18. } finally {
  19. lock.unlock();
  20. }
  21. return true;
  22. } 
  23.  
  1. //新元素堆内上浮实现
  1. private static <T> void siftUpComparable(int k, T x, Object[] array) {
  2. Comparable<? super T> key = (Comparable<? super T>) x; //尝试转化插入对象为Comparable实例
  3. while (k > 0) {
  4. int parent = (k - 1) >>> 1; // 新元素x的数组下标为k,对应的父节点的下标为(k-1)/2
  5. Object e = array[parent];
  6. if (key.compareTo((T) e) >= 0) //如果子节点已经比父节点还要大,不需要再跟上层节点比较,新元素上浮结束
  7. break;
  8. array[k] = e; //如果子节点已经比父节点小,父节点下沉,新元素上浮一次
  9. k = parent; //新元素上浮后继续与新的父节点比较大小,直到k=0或者新的父节点小于新元素
  10. }
  11. array[k] = key;//新元素在堆中插入正确的位置。
  12. }

一 弹出元素出队

  1. public E poll() {
  2. final ReentrantLock lock = this.lock;
  3. lock.lock();
  4. try {
  5. return dequeue();
  6. } finally {
  7. lock.unlock();
  8. }
  9. }
  10.  
  11. private E dequeue() {
  12. int n = size - 1;
  13. if (n < 0)
  14. return null;
  15. else {
  16. Object[] array = queue;
  17. E result = (E) array[0];
  18. E x = (E) array[n];
  19. array[n] = null;
  20. Comparator<? super E> cmp = comparator;
  21. if (cmp == null)
  22. siftDownComparable(0, x, array, n);//堆顶的最小值被弹出了,堆顶变成了空节点,空节点开始下浮到合适位置后用数组最后子节点填充。
  23. else
  24. siftDownUsingComparator(0, x, array, n, cmp);
  25. size = n;
  26. return result;
  27. }
  28. }
  1. //空元素堆内下沉实现
    private static <T> void siftDownComparable(int k, T x, Object[] array, int n) {
  2. if (n > 0) {
  3. Comparable<? super T> key = (Comparable<? super T>) x;
  4. int half = n >>> 1; // loop while a non-leaf half最后一个有子节点的父节点下标
  5. while (k < half) {
  6. int child = (k << 1) + 1; // assume left child is least
  7. Object c = array[child];
  8. int right = child + 1;
  9. if (right < n
  10. && ((Comparable<? super T>) c)
  11. .compareTo((T) array[right]) > 0)
  12. c = array[child = right]; //比较出左右子节点更小的那个子节点
  13. if (key.compareTo((T) c) <= 0) //如果左右子节点的最小值大于数组末尾的值,那么数组末尾的值直接放到父节点,空节点下沉结束
  14. break;
  15. array[k] = c; // 如果子节点最小值小于数据末尾的值,子节点上浮到父空节点
  16. k = child; //空节点下滑到最小子节点的位置
  17. }
  18. array[k] = key; // 最后空节点填充数组最后的值
  19. }
  20. }

参考资料:数据结构之优先队列--二叉堆(Java实现) 



PriorityBlockingQueue优先队列的二叉堆实现的更多相关文章

  1. 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)

    [0]README 0.1)为什么有这篇文章?因为 Dijkstra算法的优先队列实现 涉及到了一种新的数据结构,即优先队列(二叉堆)的操作需要更改以适应这种新的数据结构,我们暂且吧它定义为Dista ...

  2. 《Algorithms算法》笔记:优先队列(2)——二叉堆

    二叉堆 1 二叉堆的定义 堆是一个完全二叉树结构(除了最底下一层,其他层全是完全平衡的),如果每个结点都大于它的两个孩子,那么这个堆是有序的. 二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组 ...

  3. 优先队列的二叉堆Java实现

    package practice; import edu.princeton.cs.algs4.StdRandom; public class TestMain { public static voi ...

  4. 优先队列之二叉堆与d-堆

    二叉堆简介 平时所说的堆,若没加任何修饰,一般就是指二叉堆.同二叉树一样,堆也有两个性质,即结构性和堆序性.正如AVL树一样,对堆的以此操作可能破坏者两个性质中的一个,因此,堆的操作必须要到堆的所有性 ...

  5. 数据结构与算法——优先队列类的C++实现(二叉堆)

    优先队列简单介绍: 操作系统表明上看着是支持多个应用程序同一时候执行.其实是每一个时刻仅仅能有一个进程执行,操作系统会调度不同的进程去执行. 每一个进程都仅仅能执行一个固定的时间,当超过了该时间.操作 ...

  6. 纯数据结构Java实现(6/11)(二叉堆&优先队列)

    堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...

  7. Python实现二叉堆

    Python实现二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树).二叉堆有两种:最大堆和最小堆.最大堆:父结点的键值总是大于或等于任何一个子节点的键值:最小堆: ...

  8. 二叉堆的BuildHeap操作

    优先队列(二叉堆)BuildHeap操作 \(BuildHeap(H)\)操作把\(N\)个关键字作为输入并把它们放入空堆中.显然,这可以使用\(N\)个相继的\(Insert\)操作来完成.由于每个 ...

  9. python---使用二叉堆实现的优先队列(列表)

    哟,有实用价值 可以看到,加入是随机的,而吐出是顺序的. # coding = utf-8 # 使用二叉堆实现的优先队列(列表) class BinaryHeap: def __init__(self ...

随机推荐

  1. IDEA 提交项目至Git与获取Git项目

    1.IDEA提交项目至git 注:保证已安装Git分布式管理系统,没有自行百度安装git 1)在IDEA中配置Git与GitHub a)Git: File-->Settings --> V ...

  2. 拓扑排序【p1137】 旅行计划

    Description 小明要去一个国家旅游.这个国家有\(N\)个城市,编号为\(1\)至\(N\),并且有\(M\)条道路连接着,小明准备从其中一个城市出发,并只往东走到城市\(i\)停止. 所以 ...

  3. 2,搭建一个java开发环境

    (1)java开发需要的条件? 1)适用于环境开发的jdk(里面包括了jre和加热里面包括了jvm) 2)对应开发环境的eclipse 3)如果涉及到web开发,还需要web服务器(Tomcat) ( ...

  4. hash算法散列算法

    Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是 ...

  5. EXISTS语句的子查询

    一.EXISTS运算符简介: 使用EXISTS语句可以测试集合是否为空,EXISTS语句通常与子查询结合在一起使用.只要子查询中至少返回一个值,则EXISTS语句的值就为True.EXISTS子查询的 ...

  6. Http标准协议Android网络框架——NoHttp

    NoHttp详细文档:http://doc.nohttp.net NoHttp公益测试接口:http://api.nohttp.net 支持与RxJava完美结合.支持一句话切换底层为OkHttp,支 ...

  7. 设计模式之建造者模式(php实现)

    github地址:https://github.com/ZQCard/design_pattern/** * 建造者模式 * 将一个复杂对象的建造与调用者分离.调用者只需要给出指定对象的类型和内容,建 ...

  8. 鸟哥的linux私房菜学习记录之计算机概论

  9. Myeclipse 编译等级

    1.Java compiler level does not match the version of the installed Java project facet. 问题描述:编译等级不匹配 解 ...

  10. CentOS7.4 x64环境Percona-Server-5.6安装

    CentOS7.4 x64环境Percona-Server-5.6安装 下载MySQL $ cd /usr/local/src/ $ wget https://www.percona.com/down ...