【问题标题】:Change priorityQueue to max priorityqueue将 priorityQueue 更改为最大优先级队列
【发布时间】:2012-06-15 17:14:58
【问题描述】:

我在 Java 中有整数的优先级队列:

 PriorityQueue<Integer> pq= new PriorityQueue<Integer>();

当我调用 pq.poll() 时,我得到了最小元素。

问题:如何更改代码以获得最大元素?

【问题讨论】:

  • 我认为您应该使用接收比较器的构造函数。使用 Collections.reverseOrder 获取反向比较器。
  • 你需要传递一个比较器。见stackoverflow.com/questions/683041/…

标签: java collections priority-queue


【解决方案1】:

您可以提供一个自定义的Comparator 对象,以相反的顺序排列元素:

PriorityQueue<Integer> pq = new PriorityQueue<Integer>(defaultSize, new Comparator<Integer>() {
    public int compare(Integer lhs, Integer rhs) {
        if (lhs < rhs) return +1;
        if (lhs.equals(rhs)) return 0;
        return -1;
    }
});

现在,优先级队列将反转其所有比较,因此您将获得最大元素而不是最小元素。

希望这会有所帮助!

【讨论】:

  • 也许对于最大优先级 q,lhs
  • 对于反向打印,即如果在优先级队列中首先打印最高元素,则应该是if (rhs &lt; lhs) return +1;if (rhs &gt; lhs) return -1;
  • @Diksha 我相信我拥有的代码与您发布的代码相同。我刚刚使用了大于关系而不是小于关系。
  • 其实我的错..我的意思是应该是这样的:if (lhs &lt; rhs) return +1; if (lhs &gt; rhs) return -1;
  • @ShrikantPrabhu 很好 - 现在已经修复了!
【解决方案2】:

这样怎么样:

PriorityQueue<Integer> queue = new PriorityQueue<>(10, Collections.reverseOrder());
queue.offer(1);
queue.offer(2);
queue.offer(3);
//...

Integer val = null;
while( (val = queue.poll()) != null) {
    System.out.println(val);
}

Collections.reverseOrder() 提供了一个Comparator,在这种情况下,它会按照与自然顺序相反的顺序对PriorityQueue 中的元素进行排序。

【讨论】:

  • Collections.reverseOrder() 也被重载以获取比较器,因此如果您比较自定义对象,它也可以工作。
  • Java 8 的 PriorityQueue 有一个新的构造函数,它只是将比较器作为参数PriorityQueue(Comparator&lt;? super E&gt; comparator)
【解决方案3】:

您可以使用MinMaxPriorityQueue(它是 Guava 库的一部分): here's the documentation。您需要调用pollLast() 方法,而不是poll()

【讨论】:

    【解决方案4】:

    这是一个 Java 中的 Max-Heap 示例:

    PriorityQueue<Integer> pq1= new PriorityQueue<Integer>(10, new Comparator<Integer>() {
    public int compare(Integer x, Integer y) {
    if (x < y) return 1;
    if (x > y) return -1;
    return 0;
    }
    });
    pq1.add(5);
    pq1.add(10);
    pq1.add(-1);
    System.out.println("Peek: "+pq1.peek());
    

    输出将是 10

    【讨论】:

      【解决方案5】:

      我刚刚在双堆排序最小值最大值的两个比较器上运行了蒙特卡罗模拟,它们都得出了相同的结果:

      这些是我使用的最大比较器:

      (A) 集合内置比较器

       PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(Collections.reverseOrder());
      

      (B) 自定义比较器

      PriorityQueue<Integer> heapLow = new PriorityQueue<Integer>(new Comparator<Integer>() {
          int compare(Integer lhs, Integer rhs) {
              if (rhs > lhs) return +1;
              if (rhs < lhs) return -1;
              return 0;
          }
      });
      

      【讨论】:

      • 对于反向打印,即如果在优先级队列中首先打印最高的元素,它应该是if (rhs &lt; lhs) return +1; if (rhs > lhs) return -1;
      • 您可以根据需要进行编辑。我没有时间确认你写了什么。在我的设置中,我写的是正确的
      【解决方案6】:
      PriorityQueue<Integer> pq = new PriorityQueue<Integer> (
        new Comparator<Integer> () {
          public int compare(Integer a, Integer b) {
             return b - a;
          }
        }
      );
      

      【讨论】:

      • 有什么问题?
      • 这是完美的,并且通过将最小堆转换为最大堆来完成所要求的任务。
      • 使用b-a会导致overflow,所以应该避免使用它,应该使用Collections.reverseOrder();作为比较器或用Integer.compare(a,b);替换b-a,Integer.compare(a,b);已经添加到Java 8
      【解决方案7】:

      您可以尝试使用反向符号推送元素。例如:添加 a=2 & b=5 然后轮询 b=5。

      PriorityQueue<Integer>  pq = new PriorityQueue<>();
      pq.add(-a);
      pq.add(-b);
      System.out.print(-pq.poll());
      

      一旦您轮询队列的头部,请反转符号以供您使用。 这将打印 5(更大的元素)。可以在幼稚的实现中使用。绝对不是可靠的解决方法。我不推荐它。

      【讨论】:

        【解决方案8】:

        您可以从 Java 8 开始使用 lambda 表达式。

        以下代码将打印 10,较大的。

        // There is overflow problem when using simple lambda as comparator, as pointed out by Фима Гирин.
        // PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x);
        
        PriorityQueue<Integer> pq =new PriorityQueue<>((x, y) -> Integer.compare(y, x));
        
        pq.add(10);
        pq.add(5);
        System.out.println(pq.peek());
        

        lambda 函数将两个整数作为输入参数,将它们相减,然后返回算术结果。 lambda 函数实现了函数接口Comparator&lt;T&gt;。 (与匿名类或离散实现相反,这是就地使用的。)

        【讨论】:

        • lambda 函数,将其输入参数命名为 x 和 y 并返回 y-x,这基本上是 int 比较器类所做的,只是它返回 x-y
        • (x, y) -&gt; y - x 这样的比较器由于溢出可能不适合长整数。例如,数字 y = Integer.MIN_VALUE 和 x = 5 会产生正数。最好使用new PriorityQueue&lt;&gt;((x, y) -&gt; Integer.compare(y, x))。不过,@Edwin Dalorzo 给出了更好的解决方案来使用Collections.reverseOrder()
        • @ФимаГирин 这是真的。 -2147483648 - 1 变为 2147483647
        【解决方案9】:

        优先级队列的元素根据其自然顺序或队列构建时提供的比较器进行排序。

        Comparator 应该覆盖 compare 方法。

        int compare(T o1, T o2)
        

        默认比较方法返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个。

        Java 提供的 Default PriorityQueue 是 Min-Heap,如果你想要一个 max heap 下面是代码

        public class Sample {
            public static void main(String[] args) {
                PriorityQueue<Integer> q = new PriorityQueue<Integer>(new Comparator<Integer>() {
        
                    public int compare(Integer lhs, Integer rhs) {
                        if(lhs<rhs) return +1;
                        if(lhs>rhs) return -1;
                        return 0;
                    }
                });
                q.add(13);
                q.add(4);q.add(14);q.add(-4);q.add(1);
                while (!q.isEmpty()) {
                    System.out.println(q.poll());
                }
            }
        
        }
        

        参考:https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html#comparator()

        【讨论】:

          【解决方案10】:

          你可以试试这样的:

          PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> -1 * Integer.compare(x, y));
          

          这适用于您可能拥有的任何其他基本比较功能。

          【讨论】:

            【解决方案11】:

            这可以通过以下 Java 8 中的代码来实现,该代码引入了一个只接受比较器的构造函数。

            PriorityQueue<Integer> maxPriorityQ = new PriorityQueue<Integer>(Collections.reverseOrder());
            

            【讨论】:

              【解决方案12】:
              PriorityQueue<Integer> lowers = new PriorityQueue<>((o1, o2) -> -1 * o1.compareTo(o2));
              

              【讨论】:

                【解决方案13】:

                将 PriorityQueue 更改为 MAX PriorityQueue 方法一:队列 pq = new PriorityQueue(Collections.reverseOrder()); 方法二:队列 pq1 = new PriorityQueue((a, b) -> b - a); 让我们看几个例子:

                public class Example1 {
                    public static void main(String[] args) {
                
                        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
                        Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
                        pq.addAll(ints);
                        System.out.println("Priority Queue => " + pq);
                        System.out.println("Max element in the list => " + pq.peek());
                        System.out.println("......................");
                        // another way
                        Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
                        pq1.addAll(ints);
                        System.out.println("Priority Queue => " + pq1);
                        System.out.println("Max element in the list => " + pq1.peek());
                        /* OUTPUT
                          Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
                          Max element in the list => 888
                          ......................
                           Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
                           Max element in the list => 888
                
                         */
                
                
                    }
                }
                

                让我们来一次著名的采访 问题:使用 PriorityQueue 的数组中的第 K 个最大元素

                public class KthLargestElement_1{
                    public static void main(String[] args) {
                
                        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
                        int k = 3;
                        Queue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
                        pq.addAll(ints);
                        System.out.println("Priority Queue => " + pq);
                        System.out.println("Max element in the list => " + pq.peek());
                        while (--k > 0) {
                            pq.poll();
                        } // while
                        System.out.println("Third largest => " + pq.peek());
                /*
                 Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222]
                Max element in the list => 888
                Third largest => 666
                
                 */
                    }
                }
                

                另一种方式:

                public class KthLargestElement_2 {
                    public static void main(String[] args) {
                        List<Integer> ints = Arrays.asList(222, 555, 666, 333, 111, 888, 777, 444);
                        int k = 3;
                
                        Queue<Integer> pq1 = new PriorityQueue<>((a, b) -> b - a);
                        pq1.addAll(ints);
                        System.out.println("Priority Queue => " + pq1);
                        System.out.println("Max element in the list => " + pq1.peek());
                        while (--k > 0) {
                            pq1.poll();
                        } // while
                        System.out.println("Third largest => " + pq1.peek());
                        /*
                          Priority Queue => [888, 444, 777, 333, 111, 555, 666, 222] 
                          Max element in the list => 888 
                          Third largest => 666
                
                         */
                    }
                }
                

                我们可以看到,两者都给出了相同的结果。

                【讨论】:

                  【解决方案14】:

                  这可以通过使用来实现

                  PriorityQueue<Integer> pq = new PriorityQueue<Integer>(Collections.reverseOrder());
                  

                  【讨论】:

                    【解决方案15】:

                    在 Java 8+ 中,您可以通过以下方法之一创建最大优先级队列:

                    方法一:

                    PriorityQueue<Integer> maxPQ = new PriorityQueue<>(Collections.reverseOrder()); 
                    

                    方法二:

                    PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b - a); 
                    

                    方法三:

                    PriorityQueue<Integer> maxPQ = new PriorityQueue<>((a,b) -> b.compareTo(a)); 
                    

                    【讨论】:

                    • 注意第二种方法,除非对整数有一些限制,否则最好远离这种方法。尝试将 -2147483648 和 1 插入队列时发生了什么。它将使 -2147483648 作为 1 的根。
                    【解决方案16】:

                    我们可以通过创建实现 Comparator 接口的 CustomComparator 类并覆盖其 compare 方法来做到这一点。以下是相同的代码:

                    import java.util.PriorityQueue;
                    import java.util.Comparator;
                    public class Main
                    {
                        public static void main(String[] args) {
                            PriorityQueue<Integer> nums = new PriorityQueue<>(new CustomComparator());
                            nums.offer(21);
                            nums.offer(1);
                            nums.offer(8);
                            nums.offer(2);
                            nums.offer(-4);
                            System.out.println(nums.peek());
                        }
                    }
                    class CustomComparator implements Comparator<Integer>{
                        @Override
                        public int compare(Integer n1, Integer n2){
                            int val = n1.compareTo(n2);
                            if(val > 0)
                               return -1;
                            else if(val < 0)
                                return 1;
                            else
                                return 0;
                        }
                    }
                    

                    【讨论】:

                    • compare 方法中返回n1.compareTo(n2) * (-1)n2.compareTo(n1) 可能会更容易
                    【解决方案17】:

                    使用 lamda,只需将结果与 -1 相乘即可获得最大优先级队列。

                    PriorityQueue<> q = new PriorityQueue<Integer>(
                                           (a,b) ->  -1 * Integer.compare(a, b)
                                        );
                    

                    【讨论】:

                    • 或者干脆(a,b) -&gt; b - a
                    猜你喜欢
                    • 2014-03-04
                    • 2012-02-24
                    • 2015-05-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-03-03
                    • 2010-12-24
                    相关资源
                    最近更新 更多