Cambiar la cola de prioridad a la cola de prioridad máxima

Tengo cola de prioridad en Java de enteros:

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

Cuando llamo pq.poll() Obtengo el elemento mínimo.

Pregunta: ¿cómo cambiar el código para obtener el elemento máximo?

preguntado el 12 de junio de 12 a las 20:06

Creo que deberías usar el constructor que recibe un comparador para eso. Utilice Collections.reverseOrder para obtener un comparador inverso. -

necesitas pasar un comparador. ver stackoverflow.com/questions/683041/… -

17 Respuestas

¿Qué tal esto?

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);
}

La Collections.reverseOrder() proporciona una Comparator que ordenaría los elementos en el PriorityQueue en un orden opuesto a su orden natural en este caso.

contestado el 09 de mayo de 14 a las 02:05

Collections.reverseOrder() también está sobrecargado para tomar un comparador, por lo que también funciona si compara objetos personalizados. - oveja voladora

PriorityQueue de Java 8 tiene un nuevo constructor, que solo toma el comparador como argumento PriorityQueue(Comparator<? super E> comparator). - abhisheknirmal

Puede usar la expresión lambda desde Java 8.

El siguiente código imprimirá 10, el más grande.

// 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());

La función lambda tomará dos enteros como parámetros de entrada, los restará entre sí y devolverá el resultado aritmético. La función lambda implementa la interfaz funcional, Comparator<T>. (Esto se usa en su lugar, a diferencia de una clase anónima o una implementación discreta).

Respondido el 08 de junio de 20 a las 04:06

función lambda, nombra sus parámetros de entrada x e y y devuelve yx, que es básicamente lo que hace la clase de comparación int excepto que devuelve xy - Edi Bice

El comparador como (x, y) -> y - x puede no ser apropiado para enteros largos debido al desbordamiento. Por ejemplo, los números y = Integer.MIN_VALUE y x = 5 dan como resultado un número positivo. es mejor usar new PriorityQueue<>((x, y) -> Integer.compare(y, x)). Sin embargo, la mejor solución la da @Edwin Dalorzo para usar Collections.reverseOrder(). - Фима Гирин

@ФимаГирин Eso es cierto. -2147483648 - 1 se convierte en 2147483647 - Guangdong Shen

En Java 8+ puede crear una cola de máxima prioridad a través de uno de estos métodos:

Método 1:

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

Método 2:

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

Método 3:

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

Respondido 13 Abr '20, 06:04

Tenga cuidado con el segundo método, a menos que haya algunas restricciones en los números enteros, es mejor mantenerse alejado de este método. Pruebe lo que sucedió cuando inserta -2 y 2147483648 en la cola. Hará -1 como la raíz como se supone que es 2147483648. - johnsam

Puede proporcionar un personalizado Comparator objeto que clasifica los elementos en orden inverso:

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;
    }
});

Ahora, la cola de prioridad invertirá todas sus comparaciones, por lo que obtendrá el elemento máximo en lugar del elemento mínimo.

¡Espero que esto ayude!

Respondido 11 ago 18, 17:08

tal vez para una prioridad máxima q el lhs civilizaciones

Para la impresión inversa, es decir, si los elementos más altos se van a imprimir primero en una cola de prioridad, debe ser if (rhs < lhs) return +1; if (rhs > lhs) return -1; - Tia

@Diksha Creo que el código que tengo es equivalente a lo que estás publicando. Acabo de usar la relación mayor que en lugar de menor que. - templatetypedef

en realidad, mi error ... quise decir que debería ser así: if (lhs < rhs) return +1; if (lhs > rhs) return -1; - Tia

@ShrikantPrabhu Buena captura: ¡eso ya está arreglado! - templatetypedef

PriorityQueue<Integer> pq = new PriorityQueue<Integer> (
  new Comparator<Integer> () {
    public int compare(Integer a, Integer b) {
       return b - a;
    }
  }
);

Respondido el 29 de junio de 18 a las 10:06

Cuál es el problema ? - medina

Esto es perfecto y hace exactamente lo que se pidió al convertir un montón mínimo en un montón máximo. - Kamran

usar b-a puede causar overflow por lo que debe evitar usarlo y debe usar Collections.reverseOrder(); como comparador o reemplazar ba con Integer.compare(a,b); que se ha añadido en Java 8 - yug singh

Los elementos de la cola de prioridad se ordenan según su ordenación natural o mediante un Comparador proporcionado en el momento de la construcción de la cola.

El comparador debe anular el método de comparación.

int compare(T o1, T o2)

El método de comparación predeterminado devuelve un número entero negativo, cero o un número entero positivo, ya que el primer argumento es menor, igual o mayor que el segundo.

El PriorityQueue predeterminado proporcionado por Java es Min-Heap, si desea un montón máximo, el siguiente es el código

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());
        }
    }

}

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

respondido 15 nov., 16:05

Podemos hacer esto creando nuestro Comparador personalizado clase que implementa la interfaz Comparator y anula su método de comparación. A continuación se muestra el código para el mismo:

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;
    }
}

Respondido 06 ago 20, 06:08

Probablemente sería más fácil regresar n1.compareTo(n2) * (-1) or n2.compareTo(n1) in compare método - jscherman

Esto se puede lograr usando

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

Respondido el 16 de Septiembre de 19 a las 19:09

Aquí hay una muestra de Max-Heap en Java:

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());

La salida será 10

Respondido el 14 de enero de 14 a las 20:01

Esto se puede lograr con el siguiente código en Java 8 que ha introducido un constructor que solo toma un comparador.

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

Respondido 05 Jul 18, 02:07

Puede usar el MinMaxPriorityQueue (es parte de la biblioteca Guava): aquí está la documentación. En lugar de poll(), necesitas llamar al pollLast() método.

Respondido 24 Jul 13, 17:07

Cambiar PriorityQueue a MAX PriorityQueue Método 1: Cola pq = new PriorityQueue<>(Collections.reverseOrder()); Método 2: Cola pq1 = new PriorityQueue<>((a, b) -> b - a); Veamos algunos ejemplos:

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

         */


    }
}

Tomemos un problema de entrevista famoso: Kth elemento más grande en una matriz usando PriorityQueue

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

 */
    }
}

De otra manera :

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

         */
    }
}

Como podemos ver, ambos están dando el mismo resultado.

Respondido 20 Feb 19, 14:02

Acabo de ejecutar una simulación Monte-Carlo en ambos comparadores en el mínimo máximo de ordenación de doble montón y ambos llegaron al mismo resultado:

Estos son los comparadores máximos que he usado:

(A) Comparador integrado de colecciones

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

(B) Comparador personalizado

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;
    }
});

respondido 04 mar '15, 09:03

Para la impresión inversa, es decir, si los elementos más altos se van a imprimir primero en una cola de prioridad, debe ser if (rhs < lhs) return +1; si (rhs > lhs) devuelve -1; - Tia

Puedes editarlo si quieres. No tengo tiempo para confirmar lo que escribiste. En mi configuración, lo que escribí fue correcto: civilizaciones

Puedes probar algo como:

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

Lo que funciona para cualquier otra función de comparación de base que pueda tener.

Respondido el 23 de diciembre de 17 a las 16:12

PriorityQueue<Integer> lowers = new PriorityQueue<>((o1, o2) -> -1 * o1.compareTo(o2));

respondido 29 nov., 18:06

Usando lamda, simplemente multiplique el resultado con -1 para obtener la cola de máxima prioridad.

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

Respondido 21 Oct 20, 09:10

O simplemente (a,b) -> b - a. - Abhijit Sarkar

Puede intentar empujar elementos con signo inverso. Por ejemplo: Para sumar a=2 & b=5 y luego sondear b=5.

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

Una vez que sondee el encabezado de la cola, invierta el signo para su uso. Esto imprimirá 5 (elemento más grande). Se puede utilizar en implementaciones ingenuas. Definitivamente no es una solución confiable. no lo recomiendo

contestado el 18 de mayo de 16 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.