`

PriorityQueue 优先级队列

 
阅读更多

1. 去哪儿面试的时候,被问到java源代码中有用到堆的地方吗?

     我不假思索的回到,没有!因为当初压根就没有用到过Queue相关的类!

 

     PriorityQueue就是通过Heap实现的。Heap通过数组模拟的!

      分析下他维护堆的性质,以及删除首元素时,源代码中采用的手段:

      因为PriorityQueue模拟的是队列,所以就必须遵循FIFO,所以这里存在两个维护堆的过程,

      一个从下到上 == add

     一个从上到下 == remove

     还有一个地方,要注意的就是父子节点的小标处理,一定得注意数组是从0开始,不能简单 left = 2*i;

 

   add() 插入元素 , // 通过调用offer()

  

public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException(); // 不支持null
        modCount++;
        int i = size;
        if (i >= queue.length)
            grow(i + 1); // 数组扩容
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
            siftUp(i, e); // 关键一步就在这了,维护堆的性质!在i位置插入e
        return true;
    }

 

private void siftUp(int k, E x) {
        if (comparator != null) // 可以自定义比较器,当堆对元素进行比较的时候,可以按照你的规矩来。
            siftUpUsingComparator(k, x);
        else
            siftUpComparable(k, x);
    }

 

private void siftUpComparable(int k, E x) { // 这个方法真正维护堆的性质了!使用默认的比较器
        Comparable<? super E> key = (Comparable<? super E>) x; // 可以这样用,说明E类型实现了Comparable接口!像Integer,String 默认实现来的!
        while (k > 0) {
            int parent = (k - 1) >>> 1;  // 相当于 (k - 1)/2; 取得父节点
            Object e = queue[parent];
            if (key.compareTo((E) e) >= 0) // 如果比父节点大,那么就不要比了,说明建的是一个最小堆!那么可以建最大堆吗?
                break;
            queue[k] = e;// 如果比父节点小,那么就一路递归上去,直到比父节点大或者k == 0!
            k = parent;
        }
        queue[k] = key;
    }

 poll()  移除头结点 也就是最小的节点!然后再维护堆!

   

 public E poll() {
        if (size == 0)
            return null;
        int s = --size; // 注意这里,size 的大小 -1 了 , 不要在for循环里使用 i < queue.size()一边remove一边还想着输出所有的值了!
        modCount++;
        E result = (E) queue[0];
        E x = (E) queue[s];
        queue[s] = null;// 最后一个元素为空,在priorityQueue中实际帮我们存值的是elements数组,但是我们不会看到这个数组,我们只会看到存放元素的那一部分!
        if (s != 0)
            siftDown(0, x); // 这里就要把最后一个元素插入首部,因为你现在要移除它吗,总得有个来顶替他的位置!
        return result;
    }
 

 

 

private void siftDown(int k, E x) { // 注意到他与add时的差别吗?这也满足队列的性质,队尾进队首出!队尾进维护堆就得从下往上比较,而插入到对首就得从上往下来比较了!
        if (comparator != null)
            siftDownUsingComparator(k, x);
        else
            siftDownComparable(k, x);
    }

   

private void siftDownComparable(int k, E x) { // 从下往上
        Comparable<? super E> key = (Comparable<? super E>)x;
        int half = size >>> 1;        // loop while a non-leaf   size / 2 
        while (k < half) { // k如果等于half 那么接下来计算child > size 不就会数组越界了吗?当k = half - 1时,child = 2*half - 1 right = 2*half 注意2*half不一定==size
            int child = (k << 1) + 1; // assume left child is least 相当于 k * 2 + 1 注意这里明明是左孩子,可是为什么还要+1了,要知道数组是从0开始的!
            Object c = queue[child]; 
            int right = child + 1; // 右孩子
            if (right < size &&      // 这一步就会得到左孩子 和 右孩子中的最小的节点!如果你比这个最小的节点还小,那么自然就不要下移了,如果你比左右孩子中的某一个大,那自然得       
                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0) // 最小的那个移上去啊.
                c = queue[child = right];
            if (key.compareTo((E) c) <= 0)
                break;
            queue[k] = c; // 左右孩子的最小节点上移
            k = child; // 父节点下移,继续比较 ,
        }
        queue[k] = key;
    }

 

分享到:
评论

相关推荐

    解析Java中PriorityQueue优先级队列结构的源码及用法

    优先级队列的核心特性包括: 1. **数据结构**:PriorityQueue使用二叉堆作为其数据结构,通常是一个最小堆,保证队头元素是最小的。 2. **比较规则**:队列中的元素必须实现Comparable接口,或者在创建队列时提供...

    优先级队列cpp文件PriorityQueue.cpp

    优先级队列cpp文件PriorityQueue.cpp

    PriorityQueue-MEX-Matlab 优先级队列 matlab

    总结来说,“PriorityQueue-MEX-Matlab”是一个利用MEX技术在MATLAB中实现的优先级队列库,它提供了一套高效的接口,便于在MATLAB环境中进行优先级队列的操作,如插入、删除和查询等。这个项目可能还包括了一些示例...

    优先级队列(堆实现)

    在Java中,优先级队列是通过`java.util.PriorityQueue`类来实现的,它基于一个二叉堆(Binary Heap)的数据结构。本文将深入探讨优先级队列的概念、实现方式以及如何在实际编程中使用。 首先,理解二叉堆是理解...

    一个用堆实现的优先级队列

    优先级队列是一种特殊的数据结构,它按照优先级顺序存储元素,最高优先级的元素总是在队列的前端。在计算机科学中,堆通常被用来实现优先级队列。堆是一种完全二叉树,其中每个父节点的值都大于或等于(最大堆)或...

    优先级队列头文件priorityqueue.h

    优先级队列头文件priorityqueue.h

    毕业设计MATLAB_优先级队列.zip

    PriorityQueue.m是MATLAB脚本或函数文件,很可能包含了优先级队列的实现代码。license.txt通常包含软件许可信息,说明了这些源代码的使用条件和限制。ignore.txt则可能是Git或版本控制系统中的忽略文件,指定了在...

    PriorityQueue带优先级的队列md,学习代码笔记

    **PriorityQueue带优先级的队列** `PriorityQueue`是Java集合框架中的一种特殊队列,它基于优先堆实现,可以自动对队列中的元素进行排序。与普通队列不同,`PriorityQueue`不是先进先出(FIFO)的数据结构,而是...

    排队matlab代码-MatlabPriorityQueue:为Matlab编写的优先级队列

    《MatlabPriorityQueue: 为Matlab编写的优先级队列》 在计算机科学中,优先级队列是一种特殊的数据结构,它允许我们按照优先级处理元素,而非按照它们进入队列的顺序。这种数据结构在许多算法和应用中都扮演着关键...

    java使用小根堆实现优先级队列的几种方式

    - **内部实现**:Java的`PriorityQueue`类已经实现了小根堆,我们可以通过直接使用这个类来创建优先级队列,如`PriorityQueue&lt;Integer&gt; queue = new PriorityQueue();`,然后可以调用`offer()`、`poll()`等方法进行...

    .NETPriorityQueue:使用C#中的二进制堆的自定义通用优先级队列实现。 (据我所知)它符合大多数.NET标准。不是线程安全的

    使用C#中的二进制堆的自定义优先级队列实现。为个人/俱乐部项目编写。 (据我所知)它符合大多数.NET标准。不是线程安全的。 信息 这段代码是从Java项目转换为利用C#功能集并在结构上更合理的东西。虽然原始的Java...

    Python实现一个优先级队列的方法

    以下是一个利用`heapq`实现的优先级队列类`PriorityQueue`: ```python import heapq class PriorityQueue: def __init__(self): self._queue = [] self._index = 0 def push(self, item, priority): heapq....

    Python实现优先级队列结构的方法详解

    ### Python 实现优先级队列结构的方法详解 #### 一、优先级队列概述 优先级队列(Priority Queue)是一种特殊的数据结构,它能够存储一系列具有不同优先级的元素。这种数据结构允许用户根据元素的优先级进行插入和...

    Java数组模拟优先级队列数据结构的实例

    虽然这种方法在性能上可能不如Java内置的`PriorityQueue`类高效,但对于学习理解优先级队列的工作原理和数据结构的实现是一个很好的实践。通过这种方式,我们可以更好地理解优先级队列的核心特性,以及如何通过基本...

    PriorityQueue-MEX-Matlab:这是 C++ STL 优先级队列的 Mexified MATLAB 包装器-matlab开发

    这是 C++ STL 优先级队列的 Mexified MATLAB 包装器这个优先队列实现很简单。 然而,它可以用来保存任意对象的“排序”列表。 我们可以只推送它的索引,而不是推送整个对象。 这是通过首先像往常一样将对象存储在 ...

    Java-PriorityQueue:任务优先级队列的实现

    任务的优先队列 基于任务的PriorityQueue的实现在此程序中,用户可以: 注册新任务,并传递名称和优先级 提取并返回列表中优先级最低的任务 清除任务列表 列出所有待处理的任务及其优先级 导入和导出CSV文件中的...

    Java队列源码-priority-queue:Java中优先级队列实现的源代码

    Java中的优先级队列(PriorityQueue)是一种特殊的队列,它按照元素的优先级进行排序。在Java集合框架中,PriorityQueue是位于java.util包下的一个类,它实现了Queue接口,但并不保证按照先进先出(FIFO)的顺序进行...

    Python利用heapq实现一个优先级队列的方法

    ### Python利用heapq实现优先级队列的方法 在Python中,`heapq`模块提供了一系列操作堆数据结构的函数,可以高效地实现优先级队列。优先级队列是一种特殊的队列,其中每个元素都有一个优先级,较高优先级的元素会先...

    Python cookbook(数据结构与算法)实现优先级队列的方法示例

    在优先级队列的实现中,我们定义了一个`PriorityQueue`类,它具有`push`和`pop`方法。`push`方法用于添加元素到队列中,它将新元素以及其优先级作为参数,并使用`heapq.heappush`函数将新元素添加到最小堆中。因为`...

Global site tag (gtag.js) - Google Analytics