2012-06-12 9 views
63

Ich habe Prioritätswarteschlange in Java ganzen Zahlen:ändern Priorityqueue bis max Priorityqueue

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

Als ich pq.poll() nenne ich das kleinste Element erhalten.

Frage: Wie man den Code ändert, um das maximale Element zu erhalten?

+1

Ich denke, dass Sie den Konstruktor verwenden sollten, der einen Komparator für das empfängt. Verwenden Sie den Collections.reverseOrder, um einen umgekehrten Komparator zu erhalten. –

+1

müssen Sie einen Komparator übergeben. siehe http://stackoverflow.com/questions/683041/java-how-doi-i-use-a-priorityqueue – DarthVader

Antwort

133

Wie wäre es wie folgt aus:

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

Die Collections.reverseOrder() ein Comparator bereitstellt, die die Elemente in der PriorityQueue in einer der oposite, um ihre natürliche Ordnung in diesem Fall sortieren würde.

+9

' Collections.reverseOrder() 'ist ebenfalls überladen, um einen Vergleicher zu verwenden, daher funktioniert es auch, wenn Sie benutzerdefinierte Objekte vergleichen. –

+7

Die PriorityQueue von Java 8 hat einen neuen Konstruktor, der den Vergleicher nur als Argument 'PriorityQueue (Comparator comparator) 'verwendet. – nickspol

13

Sie können eine benutzerdefinierte Comparator Objekt zur Verfügung stellen, die in der umgekehrten Reihenfolge zählt:

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

die Prioritätswarteschlange wird nun alle seine Vergleiche umkehren, so dass Sie nicht das maximale Element erhalten wird als das kleinste Element.

Hoffe, das hilft!

+0

Gibt es einen Konstruktor, der nur einen Komparator als Parameter erhält? Weil ich nur einen sehen kann, der eine anfängliche Kapazität und einen Komparator erhält –

+1

@ EdwinDalorzo- Whoops, diesen Parameter vergessen. Danke, dass Sie das bemerkt haben und behoben haben. – templatetypedef

+5

vielleicht für eine maximale Priorität q die Lhs sivi

2

Sie können MinMaxPriorityQueue verwenden (es ist ein Teil der Guava-Bibliothek): here's the documentation. Anstelle von poll() müssen Sie die pollLast() Methode aufrufen.

3

Hier ein Beispiel Max-Heap in 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()); 

wird der Ausgang 10 sein

0

Ich lief eine Monte-Carlo-Simulation auf beiden Komparatoren auf Doppelstapelsortier-min max und sie beide kam zu dem gleichen Ergebnis:

Dies sind die Komparatoren max ich verwendet habe:

(A) Sammlungen eingebauter Komparator

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

(B) Individuelle Komparator

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

Für umgekehrtes Drucken, das heißt, wenn die höchsten Elemente zuerst in einer Prioritätswarteschlange gedruckt werden sollen, sollte es sein: if (rhs lhs) gibt -1 zurück; – Tia

+0

Sie können es bearbeiten, wenn Sie möchten. Ich habe keine Zeit zu bestätigen, was du geschrieben hast. In meiner Einrichtung war das, was ich geschrieben habe, korrekt – sivi

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

Was ist das Problem? – CMedina

+0

Dies ist perfekt und genau das, was gefragt wurde, indem ein Min-Heap in einen Max-Heap umgewandelt wurde. – Kamran

0

Sie können versuchen, Elemente mit umgekehrtem Vorzeichen schieben. ZB: Um a = 2 & b = 5 und dann poll b = 5.

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

Sobald Sie den Kopf der Warteschlange abgefragt haben, kehren Sie das Zeichen für Ihre Verwendung um. Dies wird 5 drucken (größeres Element). Kann in naiven Implementierungen verwendet werden. Definitiv keine zuverlässige Lösung. Ich empfehle es nicht.

29

können Sie Lambda-Ausdruck, da Java verwenden 8.

Der folgende Code wird 10 drucken, desto größer ist.

PriorityQueue<Integer> pq = new PriorityQueue<>((x, y) -> y - x); 
pq.add(10); 
pq.add(5); 
System.out.println(pq.peek()); 

Die Lambda-Funktion wird zwei ganze Zahlen als Eingangsparameter nehmen, um sie voneinander subtrahieren, und gibt das arithmetische Ergebnis.Die Lambda-Funktion implementiert das Funktionsinterface Comparator<T>. (Dies wird anstelle einer anonymen Klasse oder einer diskreten Implementierung verwendet.)

+0

Lambda-Funktion, benennt seine Eingabeparameter x und y und gibt yx zurück, was im Grunde das ist, was die int-Vergleichsklasse tut, außer es gibt xy zurück –

+1

Der Vergleicher wie '(x, y) -> y-x' mag für lange nicht geeignet sein Integer aufgrund von Überlauf. Zum Beispiel ergeben die Zahlen y = Integer.MIN_VALUE und x = 5 eine positive Zahl. Es ist besser, 'neue PriorityQueue <> ((x, y) -> Integer.compare (y, x))' 'zu verwenden. Allerdings ist die bessere Lösung von @Edwin Dalorzo, 'Collections.reverseOrder()' zu verwenden. –

+0

@ ФимаГирин Das stimmt. -2147483648 - 1 wird 2147483647 –

6

Die Elemente der Prioritätswarteschlange werden nach ihrer natürlichen Reihenfolge geordnet oder von einem Comparator, der zum Zeitpunkt der Warteschlangenerstellung bereitgestellt wird.

Der Komparator sollte die Vergleichsmethode überschreiben.

int compare(T o1, T o2) 

Standard vergleichen Methode eine negative ganze Zahl zurückgibt, Null oder eine positive ganze Zahl als das erste Argument kleiner als, gleich oder größer als der zweite.

Der Standard Priorityqueue von Java zur Verfügung gestellt ist Min-Heap, Wenn Sie eine max Heap wollen finden Sie den Code

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

} 

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

0

Sie können wie etwas versuchen:

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

Das funktioniert für jede andere Basisvergleichsfunktion, die Sie haben könnten.