Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

ADS – Vorlesung Prof. Dr. Wolfram Conen

Ähnliche Präsentationen


Präsentation zum Thema: "ADS – Vorlesung Prof. Dr. Wolfram Conen"—  Präsentation transkript:

1 ADS – Vorlesung Prof. Dr. Wolfram Conen
Rund um Dijkstra: - Count/Bucket/Radix-Sort - Priority Queues/Heap (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

2 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Schnelles Sortieren 1 2 6 3 12 4 5 9 10 11 7 8 Situation: n (Schlüssel-)Werte aus [1,n] Keine Duplikate. Kosten? O(n) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

3 Schnelles Sortieren: (einfacher) BucketSort
Töpfe: 6 1 5 6 9 10 11 12 Ergebnis: Situation: m Töpfe, Schlüsselwerte aus [1,m],Duplikate (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

4 Schneller Sortieren: BucketSort in mehreren Phasen (Radixsort)
Situation: n Werte aus [0,,mk-1], Duplikate möglich Kosten normaler Bucketsort: O(n+mk) Idee: Wir wenden ihn mehrfach an! Beispiel: n Werte aus [0,,m2-1] Phase: Werti einfügen in Bk mit k = Werti MOD m Phase: Ergebnisliste durchlaufen, Werti nach Bk mit k = Werti DIV m, dort am ENDE anfügen (allgemein: 1. MOD m, 2. DIV m, 3. DIV m2 usw.) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

5 Schneller Sortieren: BucketSort in mehreren Phasen
Beispiel: n = m = 10, Werte aus [0,,99], 1. Phase 3 MOD 10 = 3 18 MOD 10 = 8 60 24 6 98 56 34 47 7 18 Töpfe: 3 Ergebnis 1. Phase: (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

6 Schneller Sortieren: BucketSort in mehreren Phasen
Beispiel: n = 10, Werte aus [0,,99], 2. Phase 3 6 7 24 34 56 18 98 47 60 DIV 10 = 6 18 DIV 10 = 1 Töpfe: 60 Ergebnis: (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

7 Radixsort aus anderer Sicht...
Zahlen werden nach Zifferpositionen sortiert Zuerst nach der Ziffer ganz rechts (der am wenigsten signifikanten Ziffer) Dann rücken wir nach links... In den Phasen wird „stabil“ sortiert, d.h. die relative Reihenfolge bei Gleichstand ändert sich nicht (sonst geht es nicht!) 329 457 657 839 436 720 355 720 355 436 457 657 839 329 720 329 436 839 355 457 657 329 355 436 457 657 720 839 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

8 Bucket/Radix Sort: Review
Wenn wir die Größe des Schlüsselbereichs als Konstante ansehen, dann sortieren wir zu Kosten von O(n) (mit möglicherweise großen Konstanten!) Aus einer sortieren Folge können wir zu Kosten von O(1) das minimale Element finden und entnehmen Aber Dijkstra verändert ja auch noch die Distanz-Werte der Knoten... (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

9 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Priority Queues INSERT: Warteschlangen, in die Elemente gemäß einer Priorität eingeordnet werden DELETE MIN: Es wird jeweils das Element höchster Priorität entnommen (das soll das Element mit dem minimalen Wert sein) Für uns noch wichtig: DECREASE KEY – der Wert eines Knotens verringert sich! Das sind genau die Operationen, die wir im Dijkstra brauchen: Initialer Aufbau des Queues (INSERT), Updates der Knotenwerte (DECREASE KEY), Entnahme des „besten“ Knotens (DELETE MIN) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

10 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Priority Queues Q Ã INSERT(Q,v): Füge Knoten v mit Wert Wert(v) in Priority-Queue Q ein (Q,v*) Ã DELETE MIN(Q): Liefere den Knoten mit dem minimalen Wert und lösche ihn aus dem Priority-Queue Q, liefere Q zurück Q Ã DECREASE KEY(Q,v,Wert): Verringere den Wert des Knotens v auf Wert. Anmerkung: Normalerweise geben wir Q niccht explizit zurück, weil wir nur auf einer Queue arbeiten (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

11 Priority Queues: Implementierung
Wie kann man das effizient implementieren? Z.B. mittels eines sogenannte Heaps! (wir betrachten zunächst nur die Operationen INSERT und DELETE MIN) Was ist ein Heap (=Haufen)? Das ist ein partiell-geordneter Baum: Definition: Ein partiell-geordneter (binärer) Baum ist ein binärer Wurzelbaum T, in dem für jeden Teilbaum T´ mit Wurzel w gilt: 8 y 2 T´: Wert(w) · Wert(y) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

12 Partiell-geordneter Baum
(Schlüssel-)Werte: 4 6 10 12 6 13 10 13 19 7 Alle Wurzeln erfüllen die Bedingung! Ist der Baum eindeutig? Nein. (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

13 Partiell-geordneter Baum
(Schlüssel-)Werte: 4 6 10 12 6 10 13 19 7 13 Alle Wurzeln erfüllen die Bedingung! Aber der Baum ist nicht mehr „balanciert“! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

14 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: INSERT Algorithm INSERT(Q,v) Füge v auf der ersten freien Position der untersten Ebene ein (wenn voll, neue Ebene beginnen) p à Vater(v) Solange p existiert und Wert(v) < Wert(p) tue Vertausche die Werte von p und v; v à p; p à Vater(p) Wir betrachten links-vollständige partiell geordnete Bäume: alle Ebenen bis auf die letzte sind voll besetzt auf der letzten Ebene sitzen die Knoten soweit links wie möglich (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

15 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: INSERT Algorithm INSERT(Q,v) Füge v auf der ersten freien Position der untersten Ebene ein (wenn voll, neue Ebene beginnen) p à Vater(v) Solange p existiert und Wert(v) < Wert(p) tue Vertausche die Werte von p und v; v à p; p à Vater(p) Einfügen von 5 4 6 12 13 19 7 10 p ! à v 5 Wert(v) < Wert(p)? Klar! Also: Vertauschen! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

16 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: INSERT Algorithm INSERT(Q,v) Füge v auf der ersten freien Position der untersten Ebene ein (wenn voll, neue Ebene beginnen) p à Vater(v) Solange p existiert und Wert(v) < Wert(p) tue Vertausche die Werte von p und v; v à p; p à Vater(p) Einfügen von 5 4 6 12 13 19 5 7 10 v ! à p 6 Wert(v) < Wert(p)? Klar! Also: Vertauschen! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

17 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: INSERT Algorithm INSERT(Q,v) Füge v auf der ersten freien Position der untersten Ebene ein (wenn voll, neue Ebene beginnen) p à Vater(v) Solange p existiert und Wert(v) < Wert(p) tue Vertausche die Werte von p und v; v à p; p à Vater(p) Einfügen von 5 p ! à v 4 5 12 13 19 6 7 10 6 Wert(v) < Wert(p)? Nein! Also: Fertig! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

18 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: INSERT Algorithm INSERT(Q,v) Füge v auf der ersten freien Position der untersten Ebene ein (wenn voll, neue Ebene beginnen) p à Vater(v) Solange p existiert und Wert(v) < Wert(p) tue Vertausche die Werte von p und v; v à p; p à Vater(p) Ist INSERT korrekt? Wir betrachten eine einzelne Vertauschung der Werte von v und p, es gilt also Wert(v) < Wert(p). Wert(p) ist minimal bzgl. aller Unterbäume von p (und damit aller Unterbäume von v – das gilt auch nach dem Positionswechsel!) Wg. Wert(v) < Wert(p) ist dann auch Wert(v) nach Vertauschung minimal für alle Unterbäume, also ist der neue Baum partiell geordnet (unter der Annahme, dass der Ausgangsbaum partiell geordnet war). (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

19 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: DELETE MIN Entfernen des Minimums: Algorithm DELETE MIN (Q): v* Sei w die Wurzel des Heaps mit den Söhnen sl, sr; v* à w; Sei k der letzte Knoten (unten, rechts) Wert(w) à Wert(k); Lösche k; Solange sl oder sr existieren und (Wert(w) > Wert(sl) oder Wert(w) > Wert(sr)) tue Vertausche den Wert von w mit dem Wert des Sohn mit dem kleineren Wert, dieser Sohn sei s; w à s; sl à Linker_Sohn(w); sr à Rechter_Sohn(w) Gib Q und v* zurück. 4 5 12 13 19 6 7 10 w ! à k (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

20 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: DELETE MIN Algorithm DELETE MIN (Q): v* Sei w die Wurzel des Heaps mit den Söhnen sl, sr; v* à w; Sei k der letzte Knoten (unten, rechts) Wert(w) à Wert(k); Lösche k; Solange sl oder sr existieren und (Wert(w) > Wert(sl) oder Wert(w) > Wert(sr)) tue Vertausche den Wert von w mit dem Wert des Sohn mit dem kleineren Wert, dieser Sohn sei s; w à s; sl à Linker_Sohn(w); sr à Rechter_Sohn(w) Gib Q und v* zurück. Entfernen des Minimums: w ! 6 5 12 13 19 7 10 Bedingung für s = sl erfüllt! Also: Tauschen s = sl ! sr ! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

21 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: DELETE MIN Algorithm DELETE MIN (Q): (Q, Min) Sei w die Wurzel des Heaps mit den Söhnen sl, sr; v* à w; Sei k der letzte Knoten (unten, rechts) Wert(w) à Wert(k); Lösche k; Solange sl oder sr existieren und (Wert(w) > Wert(sl) oder Wert(w) > Wert(sr)) tue Vertausche den Wert von w mit dem Wert des Sohn mit dem kleineren Wert, dieser Sohn sei s; w à s; sl à Linker_Sohn(w); sr à Rechter_Sohn(w) Gib Q und v* zurück. Entfernen des Minimums: 5 6 12 13 19 7 10 w ! sl ! sr ! Bedingung nicht erfüllt! Also: Fertig! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

22 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Heap: DELETE MIN Algorithm DELETE MIN (Q): (Q, Min) Sei w die Wurzel des Heaps mit den Söhnen sl, sr; v* à w; Sei k der letzte Knoten (unten, rechts) Wert(w) à Wert(k); Lösche k; Solange sl oder sr existieren und (Wert(w) > Wert(sl) oder Wert(w) > Wert(sr)) tue Vertausche den Wert von w mit dem Wert des Sohn mit dem kleineren Wert, dieser Sohn sei s; w à s; sl à Linker_Sohn(w); sr à Rechter_Sohn(w) Gib Q und v* zurück. Ist DELETE MIN korrekt? Wir betrachten eine einzelne vertauschung der Werte von w und s, es gilt also Wert(s) < Wert(w). Wert(s) ist minimal bzgl. aller Unterbäume von s. Es wurde ausgewählt, also ist es auch minimal im Vergleich zum anderen Kind-Baum – das gilt auch nach dem Positionswechsel!) w ist möglicherweise nicht minimal für seinen Unterbaum. Das wird aber weiterbehandelt (w sinkt dann weiter!) bis schließlich Wert(w) · Wert(sl) und Wert(w) · Wert(sr). (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

23 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Priority Queue Mit dem Heap lassen sich INSERT und DELETE MIN mit Aufwand O(log n) realisieren! Das gleiche gilt für Updates, also DECREASE KEY-Operationen (analog zu INSERT plus schnelles Auffinden, kommt noch)! Damit können wir (für sparsam besetzte Graphen) Dijkstra verbessern! (Wenn die Graphen Kanten in der Größenordnung von O(n2) haben, also z.B. jeder Knoten eine Kante zu jedem anderen Knoten hat, dann hilft alles nichts im Worst-Case, weil dann das Update bzw. die Anzahl der Vergleiche die Kosten dominiert) Wie es noch besser geht: spätere Veranstaltung (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

24 (Allgemeiner) Bucket Sort
Was ist, wenn wir viel mehr mögliche Werte, als zur Verfügung stehende Töpfe haben? Situation: n INTEGER aus dem Wertebereich [0,..,k-1], Platz für m Töpfe, k >> m (d.h. k ist deutlich größer als m). Idee: Wir teilen [0..k-1] in m Töpfe auf. z.b. k = 100, m = 5, Breite k/m, also 20 Jeder Topf steht für einen bestimmten Bereich T1: [0..19], T2: [20..39], ... Dann füllen wir die Töpfe und sortieren diese! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

25 Schnelles Sortieren: BucketSort
Töpfe: 5, Werte 10, Wertebereich [0..99] [0..19] [20..39] [40..59] [60..79] [80..99] 25 36 16 23 91 Töpfe: 12 21 48 60 89 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

26 (Allgemeiner) Bucket Sort: Aufwand
Finden des richtigen Buckets für einen Wert v durch Vergleich mit den Bucketgrenzen: Naiv: Laufe mit i von Bucket 1 bis m, Vergleiche den Wert v mit der oberen Bucketgrenze UB(Bi) Falls v <= UB(Bi), dann gehört v in Bi, stop; sonst weitersuchen Worstcase für einen einzelnen Wert: m Vergleiche (bzw. m-1, denn man muß nur bis m-1 laufen) Maximal also n*m Vergleiche, bis alle Werte ihren Platz gefunden haben (im letzten oder vorletzen Bucket) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

27 (Allgemeiner) Bucket Sort: Aufwand
Finden des richtigen Buckets für einen Wert v durch Vergleich mit den Bucketgrenzen: Besser: Binäre Suche 1: Setze aktuelles Bucketintervall [l..r] auf [1..m] 2: Falls l == r, stoppe (richtiges Intervall gefunden!) 3: Bestimme den mittleren Bucket, Bm, m = d (r+1-l)/2 e+(l-1) des Intervalls 3: Falls v · UB(Bm), dann suche weiter in [l..m] „unten“ sonst in [m+1..r] „oben“ (Update der Grenzen, zurück zu 2) Aufwand für einen Wert: O(log2(m)), für alle n*O(log2(m)) Allerdings immer! (Best case oben: alle im ersten Intervall, O(n)) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

28 (Allgemeiner) Bucket Sort: Aufwand
Binäre Suche am Beispiel: 10 Buckets [0..9],[10..19], ..., [90..99] m = 10, k = 100, Breite k/m = 10, Wert v = 27 Bucketintervall [1..10], Mittlerer Bucket: d (10+1-1) / 2 e = d 5 e = 5 Upper Bound von Bucket 5 = UB(B5) = 49, 27 <= 49? JA Bucketintervall [1..5], Mittlerer Bucket: d (5+1-1) / 2 e = d 3 e = 3 Upper Bound von Bucket 3 = UB(B3) = 29, 27 <= 29? JA Bucketintervall [1..3], Mittlerer Bucket: d (3+1-1) / 2 e = d 2 e = 2 Upper Bound von Bucket 2 = UB(B2) = 19, 27 <= 19? NEIN Bucketintervall [3..3], FERTIG. Aufwand: 3 Vergleiche von v mit Bucketgrenzen, O(log m) Zweierlogarithmus von 10 liegt zwischen 3 und 4, 23 = 8, 24 = 16 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

29 (Allgemeiner) Bucket Sort: Aufwand
Noch besser: Wir können den Bucket, in den v gehört, direkt ausrechnen! Bucketindex i = (v DIV m)+1, also ganzzahlige Division +1, weil wir hier von 1 bis m zählen, bei 0..m nicht +1. z.B. (27 DIV 10)+1 = 2+1 = 3 Kosten konstant, O(1) Man kann die Bucketaufteilung auch anders gestalten, z.B. mehr Buckets zwischen 0..49, wenn dort die meisten Werte landen, usw. (sofern man etwas über die VERTEILUNG der Werte weiß) Je nach Anzahl der Buckets und der Wertverteilung können auch andere Möglichkeiten, den Bucket für einen Wert v zu bestimmen, sinnvoll sein (s. Hashfunktionen, späteres Kapitel) Eine genaue Analyse der Durchschnittskosten hängt i.A. von der Wertverteilung und dem Verteilen der Werte auf die Buckets ab Um einen einzelnen Bucket „online“ zu sortieren, eignet sich ein HEAP ganz hervorragend! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

30 (Allgemeiner) Bucket Sort: Aufwand
Zum Platzfinden kommt der Aufwand für das Speichern in den Buckets, O(m+n) Speicher, O(m+n) Zeit m für die Zeiger/Update auf die Listen, n Einträge in den Listen (konstante Kosten für Anfügen am Beginn oder am Ende, wenn man zwei Verweise auf Anfang und Ende vorhält). Und die Kosten für das Sortieren der einzelnen Buckets! Worst-Case: alle Werte in einem Bucket, O(n log n) (z.B. mit Quicksort oder Heapsort) Best-Case: n <= m, n gleichmäßig verteilt: Sortieren kostet nichts! Average Case: hängt von der Verteilung der Werte auf die Buckets ab, wenn wir eine Gleichverteilung (Best Case!) annehmen, dann: ist d n / m e = A die Anzahl der Elemente in einem Bucket, Sortierkosten dann m * (A log A) HINWEIS: Wenn wir log A schreiben, dann meinen wir Logarithmus zur Basis 2, es sei denn, wir geben etwas anderes an Gesamt O(n)+O(m+n)+Sortierkosten, wird durch Maximum von O(m+n) und Sortierkosten (O(n log n) im Worst Case) dominiert (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

31 Weitere Alternative: Counting Sort
n INTEGER, Werte aus [0..k], k = O(n) Idee: Wir zählen zu jedem Wert i aus 0..k, wie oft er in der Eingabe vorkommt, das halten wir in einem Array C fest. Kosten (k) für Initialisierung auf 0, (n) für das Zählen Dann bestimmen wir zu jedem Wert i aus 0..k, wieviele Werte in der Eingabe kleiner oder gleich i sind, wir verändern C entsprechend Kosten (k) Wenn alle Werte aus der Eingabe verschieden sind, dann gibt C[v] für jeden Wert v die Position im Ergebnisarray an Wenn es keine Duplikate gibt, ist das Overkill, dann geht auch das direkte sortierte Ablegen auf der ersten Folie! Um auch mit Duplikaten umgehen zu können, dekrementieren wir C[v] um eins, sobald v abgelegt wurde Kosten (n) Gesamtkosten (k + n), for k = O(n) also (n) (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

32 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Counting Sort Eingabe: n = 8, k = 5 Eingabe- und Ausgabearray laufen von 1 bis n. Counting Sort: C auf 0 initialisieren Vorkommen zählen Anzahl <= bestimmen Eingabe sortieren 2 5 3 1 2 3 4 5 1 2 3 4 5 7 8 1 2 3 4 5 C: 2 4 7 1 2 3 6 7 Resultat: 2 2 3 3 3 5 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

33 Counting Sort ist STABIL
Stabiles Sortieren: Eingabezahlen mit dem gleichen Wert behalten in der Ausgabe die relative Reihenfolge ihres Auftretens in der Eingabe bei. (Counting Sort ist genau „umgekehrt“ stabil...man kann aber auch von rechts die Eingabe in das Ergebnisarray einsortieren, dann bleibt die relative Reihenfolge, z.B. der 2er, „stabil“) Normalerweise nur wichtig, wenn an dem Schlüssel noch weitere Daten hängen und diese nach einem weiteren Kriterium „vorsortiert“ sind, z.B. Adressensortieren zuerst nach Hausnummer, dann nach Strassennamen macht man natürlich schlauer durch Gruppierung: zuerst nach Strassennamen, dann Gruppenweise nach Hausnummer – mit einem stabilen Sortierverfahren geht es aber so wie oben direkt ohne Gruppenbildung Für uns aber eine wichtige Eigenschaft beim Radixsort! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta

34 (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta
Übungen Es ist ausreichend, nur die Pflichtaufgaben abzugeben (2mal nicht abgeben ist ok) – natürlich sollte man ALLE Übungsaufgaben im eigenen Interesse machen! Bei Diplom-Studenten werden die alten Inhalte von SS04 geprüft (s. Webseite), viele Inhalte sind noch „gültig“, sie können also diese Vorlesung hier hören, sie brauchen nicht abgeben. „Alte“ Bachelorstudenten sollten diese Veranstaltung hören – alte Bachelor nehmen an der ADS-Prüfung ganz normal teil! Sie müssen keine Übungsblätter abgeben – aber machen sie die Übungen in ihrem eigenen Interesse! (c) W. Conen, FH GE, ADS, Vorlesung 2, Version 1.0beta


Herunterladen ppt "ADS – Vorlesung Prof. Dr. Wolfram Conen"

Ähnliche Präsentationen


Google-Anzeigen