如何使用优先级队列?

2022-08-31 04:37:25

如何获取优先级队列以根据我希望它排序的内容进行排序?

另外,优惠添加方法之间有区别吗?


答案 1

使用构造函数重载,它采用 a 并传入比较器,比较器以适合您的排序顺序进行比较。如果您给出一个您希望如何排序的示例,如果您不确定,我们可以提供一些示例代码来实现比较器。(不过这很简单。Comparator<? super E> comparator

正如在其他地方所说:并且只是不同的接口方法实现。在我得到的JDK源代码中,调用.尽管并且由于能够指示由于大小限制而无法添加值,因此通常具有不同的行为,但这种差异与无限无关。offeraddaddofferaddofferofferPriorityQueue

下面是按字符串长度排序的优先级队列的示例:

// Test.java
import java.util.Comparator;
import java.util.PriorityQueue;

public class Test {
    public static void main(String[] args) {
        Comparator<String> comparator = new StringLengthComparator();
        PriorityQueue<String> queue = new PriorityQueue<String>(10, comparator);
        queue.add("short");
        queue.add("very long indeed");
        queue.add("medium");
        while (queue.size() != 0) {
            System.out.println(queue.remove());
        }
    }
}

// StringLengthComparator.java
import java.util.Comparator;

public class StringLengthComparator implements Comparator<String> {
    @Override
    public int compare(String x, String y) {
        // Assume neither string is null. Real code should
        // probably be more robust
        // You could also just return x.length() - y.length(),
        // which would be more efficient.
        if (x.length() < y.length()) {
            return -1;
        }
        if (x.length() > y.length()) {
            return 1;
        }
        return 0;
    }
}

下面是输出:

中等

确实很长


答案 2

Java 8 解决方案

我们可以在Java 8中使用或引入。如果我们在优先级队列中存储了一些字符串值(容量为5),我们可以提供内联比较器(基于字符串的长度):lambda expressionmethod reference

使用 lambda 表达式

PriorityQueue<String> pq=
                    new PriorityQueue<String>(5,(a,b) -> a.length() - b.length());

使用方法引用

PriorityQueue<String> pq=
                new PriorityQueue<String>(5, Comparator.comparing(String::length));

然后,我们可以将它们中的任何一个用作:

public static void main(String[] args) {
        PriorityQueue<String> pq=
                new PriorityQueue<String>(5, (a,b) -> a.length() - b.length());
       // or pq = new PriorityQueue<String>(5, Comparator.comparing(String::length));
        pq.add("Apple");
        pq.add("PineApple");
        pq.add("Custard Apple");
        while (pq.size() != 0)
        {
            System.out.println(pq.remove());
        }
    }

这将打印:

Apple
PineApple
Custard Apple

要反转顺序(将其更改为最大优先级队列),只需更改内联比较器中的顺序或使用:reversed

PriorityQueue<String> pq = new PriorityQueue<String>(5, 
                             Comparator.comparing(String::length).reversed());

我们还可以使用:Collections.reverseOrder

PriorityQueue<Integer> pqInt = new PriorityQueue<>(10, Collections.reverseOrder());
PriorityQueue<String> pq = new PriorityQueue<String>(5, 
                Collections.reverseOrder(Comparator.comparing(String::length))

因此,我们可以看到 它被重载为采用比较器,这对于自定义对象很有用。实际用途:Collections.reverseOrderreversedCollections.reverseOrder

default Comparator<T> reversed() {
    return Collections.reverseOrder(this);
}

offer() vs add()

根据文档

如果可能,报价方法将插入一个元素,否则返回 false。这与 Collection.add 方法不同,后者可能仅通过引发未经检查的异常来无法添加元素。报价方法设计用于故障是正常现象,而不是异常情况,例如,在固定容量(或“有界”)队列中。

使用容量受限的队列时,offer() 通常比 add() 更可取,因为 add() 只能通过引发异常来插入元素。优先级队列是基于优先级堆的无界优先级队列。


推荐