19. ovember 2012 Prioritätswarteschlangen und Priority Queues and Ferd van denhoven Fontys Hogeschool voor Techniek en Logistiek Venlo Software ngineering 19. ovember 2012 D/FHTBM Priority Queues and 19. ovember 2012 1/34 Prioritätswarteschlangen und Prioritätswarteschlangen und Was ist eine Prioritätswarteschlange? s ist eine Warteschlange (queue) s gibt eine Prioritätsregel, die zu jedem Zeitpunkt auf ein lement mit höchster Priorität verweist. Wird ein neues lement in die Warteschlange geschrieben, kann das ein neues dringendstes lement bedeuten. ft ist der größte Schlüssel der mit der höchsten Priorität; die Bedeutung des Schlüssels bezieht sich dann auf die betreffende nwendung. ine Prioritätswarteschlange ist eine Datenstruktur von lementen mit Schlüsseln, die zwei grundlegende perationen unterstützt: ein neues lement einfügen und das lement mit dem größten Schlüssel löschen. D/FHTBM Priority Queues and 19. ovember 2012 2/34 Prioritätswarteschlangen und Prioritätswarteschlangen (2) Prioritätswarteschlangen werden für viele lgorithmen genutzt. Sehen wir uns zunächst ein Sortier-lgorithmus an. Wir wollen eine Datenstruktur erzeugen und pflegen, die Datensätze mit numerischen Schlüsseln (priorities) enthält. Die Basisoperationene sind: ine Prioritätswarteschlange aus gegebenen lementen erzeugen. in neues lement einfügen. Das Maximum lement löschen. Sonstige perationen sind: Die Priorität eines willkürlich festgelegten lements ändern. in willkürlich festgelegtes lement löschen. Zwei Prioritätswarteschlangen zu einer großen verbinden. D/FHTBM Priority Queues and 19. ovember 2012 3/34 1
19. ovember 2012 Prioritätswarteschlangen und Basis-DT Prioritätswarteschlange adt { MaxPQ MaxPQ () void insert (it: Item ) Item getmax () // optional MaxPQ ( maxsize : int ) Item delmax () boolean ismpty () int size () Die meiste perationen von Prioritätswarteschlangen sind im diesem DT Interface. D/FHTBM Priority Queues and 19. ovember 2012 4/34 Prioritätswarteschlangen und Stacks und Warteschlangen: es gibt perationen mit konstanter Zeit perationen zum infügen UD Löschen des Maximums in konstanter Zeit sind schwieriger Sequenz geordnet halten: Maximum in konstanter Zeit löschen und finden; nicht für infügen Sequenz nicht geordnet halten: in konstanter Zeit einfügen; nicht für Maximum löschen und finden ifrig oder faul (eager/lazy): eine faule Implementierung wartet, bis die rbeit notwendig wird Trade-off bei doppelt verketteten Listen: Löschen in konstanter Zeit versus mehr Platz für die Links D/FHTBM Priority Queues and 19. ovember 2012 5/34 Prioritätswarteschlangen und rray Implementierung einer Prioritätswarteschlange (lgorithm 2.6) public class MaxPQ <Key extends Comparable <Key >> { private Key [] pq; private int = 0; public MaxPQ ( int max ) { pq = ( Key []) new Comparable [ max + 1]; public void insert ( Key x) { pq [++ ] = x; swim (); public Key delmax () { Key max = pq [1]; exch (1, - -); pq[ +1] = null ; sink (1); return max ; D/FHTBM Priority Queues and 19. ovember 2012 6/34 2
19. ovember 2012 Prioritätswarteschlangen und Worst case Kosten von Prioritätswarteschlange-perationen Basis-Methoden: unsortierte rrays und Listen Fortschrittlichere Methoden: Heap und Warteschlange. insert remove max find max ordered array: 1 1 ordered list: 1 1 unordered array: 1 unordered list: 1 heap: lg() lg() 1 best in theory: 1 lg() 1 D/FHTBM Priority Queues and 19. ovember 2012 7/34 Prioritätswarteschlangen und Heap-geordneter Baum und Heap lgorithmen für (heap ordered) in Baum ist als Heap geordnet, wenn der Schlüssel jedes Knotens größer oder gleich den Schlüsseln seiner Kind-Knoten ist (wenn es Kind-Knoten gibt). (proposition.) Der größten Schlüsselwert in einen Heap-geordneter Binärbaum findet man im Root. Der Heap-geordnete Baum sollte vollständig sein: alle Levels befüllt, ausnahme das untere. Siehe nächste Folie. (proposition P.) Die Höhe einer vollständigen Binärbaum mit Knoten ist lg(). D/FHTBM Priority Queues and 19. ovember 2012 8/34 Prioritätswarteschlangen und lgorithmen für eines Heap-geordneten Baums. X T G S M R I rray Implementeierung (Level-rdnung, Start ab rray-index 1) 1 2 3 4 5 6 7 8 9 10 11 12 X T G S M R I D/FHTBM Priority Queues and 19. ovember 2012 9/34 3
19. ovember 2012 Prioritätswarteschlangen und Heap-geordneter Baum und Heap lgorithmen für Wenn der Binärbaum vollständig ist, hat der Knoten an Position i (level-order) als lternknoten den Knoten an [i/2]. Umgekehrt hat ein Knoten an Position i seine Kindknoten (wenn es welche gibt) an den Positionen 2 i und 2 i + 1. s ist eine Darstellung als rray möglich, bei der es zwischen einem Knoten und seinem ltern- und den Kindknoten keine Links geben muss, wie wir sie in einer verketteten Darstellung brauchen. Denken Sie daran, dass es auf allen Pfaden in einem vollständigen Baum von Knoten ungefähr lg() Knoten gibt ( < 1 + 2 + 4 +... + /8 + /4 + /2) umber of levels = lg(). D/FHTBM Priority Queues and 19. ovember 2012 10/34 Heapifying Prioritätswarteschlangen und lgorithmen für Die Heap-Bedingung erfüllen: Heapifying oder den Heap reparieren. Die Heap-Bedingung ist ein sogenannter Invariant (etwas das sich nicht ändern darf), jede peration auf einen Heap muss diesen Invariant erfüllen. Wird der Schlüssel eines Knotens größer als der Schlüssel seines lternknotens, vertauschen Sie einfach den Knoten und seinen lternknoten. Falls nötig, wiederholen Sie das. Wird der Schlüssel eines Knotens kleiner als der Schlüssel eines oder beider Kindknoten, vertauschen Sie einfach den Knoten und den Kindknoten mit dem größten Schlüssel. Falls nötig, wiederholen Sie das. Swim and sink Methoden (siehe nächste Folie) bieten die Hilfsmittel zum Reparieren des, nachdem ein lement eingefügt oder seine Priorität geändert wurde. D/FHTBM Priority Queues and 19. ovember 2012 11/34 Prioritätswarteschlangen und lgorithmen für Bottum-up and bottum-down heapify help methods private void swim ( int k) { while (k > 1 && less (k/2, k)) { exch (k, k /2); k = k /2; private void sink ( int k, int ) { while (2* k <= ) { int j =2* k; if (j< && less (j, j +1)) j ++; if (! less (k, j)) break ; exch (k, j); k = j; D/FHTBM Priority Queues and 19. ovember 2012 12/34 4
19. ovember 2012 Heapify (swim) Prioritätswarteschlangen und lgorithmen für X S G R T I M Kind T von lter S... die Heapkondition. D/FHTBM Priority Queues and 19. ovember 2012 13/34 Heapify (swim) Prioritätswarteschlangen und lgorithmen für X T P G S R I M Knoten T hat sich zweimal durch umtauschen mit seinem lternknoten hoch bewegt damit die Heap-Bedingung wieder erfüllt ist. D/FHTBM Priority Queues and 19. ovember 2012 14/34 Heapify (sink) Prioritätswarteschlangen und lgorithmen für T X G S P R I M lterknoten, in diesem Fall der Rootknoten, übertretet der Heap-Bedingung. D/FHTBM Priority Queues and 19. ovember 2012 15/34 5
19. ovember 2012 Heapify (sink) Prioritätswarteschlangen und lgorithmen für X T P G S R I M Knoten ist getauscht worden mit der größten Kindknoten X, und danach nochmal mit seinem größten Kindknoten P. D/FHTBM Priority Queues and 19. ovember 2012 16/34 Prioritätswarteschlangen und lgorithmen für Heap-basierte Prioritätswarteschlange public class Heap <Key > implements Iterable <Key > { private Key [] pq; private int ; private Comparator <Key > comparator ; public Heap ( Key [] keys ) { = keys. length ; pq = ( Key []) new bject [ keys. length + 1]; for ( int i = 0; i < ; i ++) pq[i +1] = keys [i]; heapify (); private void heapify () { for ( int k = /2; k >= 1; k - -) sink (k); D/FHTBM Priority Queues and 19. ovember 2012 17/34 Prioritätswarteschlangen und lgorithmen für Komplexität der lgorithmen für (Proposition Q.) 1 Die peration insert für den abstrakten Datentyp Prioritätswarteschlange lasst sich mit Heap-geordneten Bäumen so implementieren, dass insert nicht mehr als 1 + lg() Vergleiche braucht. 2 Die peration remove max für den abstrakten Datentyp Prioritätswarteschlange lässt sich so mit Heap-geordneten Bäumen implementieren dass nicht mehr als 2lg() Vergleiche nötig sind. D/FHTBM Priority Queues and 19. ovember 2012 18/34 6
19. ovember 2012 Prioritätswarteschlangen und Sortieren mit Hilfe einer Prioritätswarteschlange in rray von lementen kann man sortieren mit Hilfe einer Prioritätswarteschlange und die remove maximum Methode. Wenn die Prioritätswarteschlange ungeordnet ist, ähnelt das Programm einem Selection Sort. Wenn die Prioritätswarteschlange geordnet ist, ähnelt das Programm einem Insertion Sort. Die Implementierung im Code auf der nächste Folie ist nicht optimal: s entstehen überflüssige Kopien von lementen. infügungen in Folge zum rstellen des ist keine effiziente Methode. D/FHTBM Priority Queues and 19. ovember 2012 19/34 Prioritätswarteschlangen und rstes Sortier-Programm mit Prioritätswarteschlange class HeapSort1 { void sort ( Item [] a, int l, int r) { pqsort (a, l, r); void pqsort ( Item [] a, int l, int r) { int k; MaxPQ pq = new MaxPQ (r- l +1); for ( k = 1; k <= r; k ++) pq. insert (a[k ]); for (k = r; k >= l; k - -) a[k] = pq. getmax (); D/FHTBM Priority Queues and 19. ovember 2012 20/34 Prioritätswarteschlangen und Das Programm HeapSort1 funktioniert wie ein Selection Sort. ffizienter gehen wir durch den Heap, indem wir kleine Subheaps von unten nach oben erstellen. Jeder Knoten wird als die Wurzel eines Subheaps betrachtet, und sink funktioniert auch für solche gut. in Knoten mit zwei Subheaps als seinen Kindern wird ein Heap, indem man sink für diesen Knoten aufruft. Indem wir rückwärts für jeden Knoten sink aufrufen, stellen wir induktiv die Heap-Bedingung her. D/FHTBM Priority Queues and 19. ovember 2012 21/34 7
19. ovember 2012 Prioritätswarteschlangen und lgorithme 2.7 public void sort ( Comparable [] a) { for ( int k = /2; k >= 1; k - -) { sink (a, k, ); while ( > 1) { exch (a, 1, - -); sink (a, 1, ); (Proposition R.) Sink-basierten Heap-Konstruktion benötigt weniger als 2 Vergleiche und weniger als Vertauschungen zum erstellen einer Heap aus lementen. D/FHTBM Priority Queues and 19. ovember 2012 22/34 Prioritätswarteschlangen und rray-indexen in heap Baum 1 2 3 4 5 /2 7 8 9 10 11-1 ist ungerade: letzte Knoten mit Kindknoten hat 2 KindKnoten. Knoten bei Index /2 ist der letzte Knoten mit Kindknoten; auch wenn gerade ist. D/FHTBM Priority Queues and 19. ovember 2012 23/34 Prioritätswarteschlangen und rray-indexen in heap Baum (2) 1 2 3 4 5 /2 7 8 9 10-1 ist gerade: letzte Knoten mit Kindknoten hat 1 KindKnoten. Knoten bei Index /2 ist der letzte Knoten mit Kindknoten; auch wenn ungerade ist. D/FHTBM Priority Queues and 19. ovember 2012 24/34 8
19. ovember 2012 Prioritätswarteschlangen und Sink-Methode mehr detailliert private void sink ( int k, int ) { while (2* k <= ) { // 1 int j =2* k; // 2 if (j< && less (j, j +1)) j ++; // 3 if (! less (k, j)) break ; // 4 exch (k, j); k = j; // 5 1 Knoten auf k hat links Kind auf 2 k, stop wenn 2 k >. 2 Start bei linker Knoten mit j. ls j == dann j gerade: kein rechter Knoten. Genaue Behandlung von der letzte Knoten! D/FHTBM Priority Queues and 19. ovember 2012 25/34 Prioritätswarteschlangen und Sink-Methode mehr detailliert (2) private void sink ( int k, int ) { while (2* k <= ) { // 1 int j =2* k; // 2 if (j< && less (j, j +1)) j ++; // 3 if (! less (k, j)) break ; // 4 exch (k, j); k = j; // 5 3 Wenn j < dann existiert rechter Knoten; Wenn j == gibt es kein rechter Kindknoten. Größtes Kind gefunden auf j. 4 Wenn Knoten auf k nicht kleiner als Knoten auf j: nichts zu tun, break. 5 Wenn Knoten auf j größer als Knoten auf k: austauschen. D/FHTBM Priority Queues and 19. ovember 2012 26/34 Prioritätswarteschlangen und rste Teil der heapsort code for ( int k = /2; k >= 1; k - -) { sink (a, k, ); Knoten mit Index k = /2 ist letzte Knoten mit Kinder (der letzte lterknoten - parent). Von hier geht s Levelorder aufwerts im Baum und heapify mittels sink. D/FHTBM Priority Queues and 19. ovember 2012 27/34 9
19. ovember 2012 Prioritätswarteschlangen und Zweiten Teil of heapsort code while ( > 1) { exch (a, 1, - -); sink (a, 1, ); In-place sortierung: vertausche max Item (Index 1) mit letzte Knoten von unsortierten Teil des Baums (Index ). Funkioniert wie selection sort llererst mit 1 reduzieren und dann heapify durch nruf von sink für neue Wurzel. D/FHTBM Priority Queues and 19. ovember 2012 28/34 Prioritätswarteschlangen und (1) Zuerst bauen wir einen Heap von unten auf, in-place. for( int k=/2; k>=1; k--) sink(k, ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 S R T I G X M P L S R T I G X M P L S R T P G X M I L S R X P G T M I L S R X P G T M I L S P R X G T M I L X P R T G S M I L X T P R S G M I L D/FHTBM Priority Queues and 19. ovember 2012 29/34 Prioritätswarteschlangen und (2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 S R T I G X M P L S R T I G X M P L S R T P G X M I L S R X P G T M I L S R X P G T M I L S P R X G T M I L S P R X G T M I L X P R S G T M I L X P R T G S M I L X P R T G S M I L X T P R G S M I L X T P R S G M I L D/FHTBM Priority Queues and 19. ovember 2012 30/34 10
19. ovember 2012 Heapified Prioritätswarteschlangen und a[-, X, T, P, R, S,,, G,,,, M, I, L, ] X T P R S G M I L ist ungerade: letzte Knoten mit Kindknoten hat 2 KindKnoten. Knoten bei Index /2 ist der letzte Knoten mit Kindknoten; auch wenn gerade ist. D/FHTBM Priority Queues and 19. ovember 2012 31/34 Prioritätswarteschlangen und (3) Dann lösschen wir jedesmal das größte element vor der Heap. Die fette Buchstaben stimmen überein mit dem schon sortierten Teil des rrays. while(>1) {exch(1,); sink(1, --); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 T S P R G M I L X S R P L G M I T X R L P I G M S T X P L I M G R S T X L I M G P R S T X L M I G P R S T X M L I G P R S T X D/FHTBM Priority Queues and 19. ovember 2012 32/34 Prioritätswarteschlangen und (4) while(>1) {exch(1,); sink(1, --); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 X T P R S G M I L T P R S G M I L X T P R S G M I L X T S P R G M I L X T S P R G M I L X D/FHTBM Priority Queues and 19. ovember 2012 33/34 11
19. ovember 2012 Prioritätswarteschlangen und igenschaften (Proposition S.) bracht weniger als 2 lg() Vergleichungen (und halb soviel Vertauschungen zum sortiern von lemente. igenschaft S und die In-place igenschaft sind aus praktischen Gründen wichtig: garantiert das In-place-Sortieren von lementen in proportionaler Zeit zu lg(). s gibt keine worst case ingabe, die signifikant verlangsamt (anders als Quicksort). braucht nicht mehr Speicherplatz (anders als Mergesort) D/FHTBM Priority Queues and 19. ovember 2012 34/34 12