Datenstrukturen - sven.köppel.org

Werbung
Datenstrukturen
Sommersemester 2010
Isolde Adler
Herzlich willkommen!
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Rubrik Links“ auf der Vorlesungshomepage
”
. . . die Links werden gelegentlich ergänzt, Sie finden dort u.A.:
• Online-Forum der Fachschaft Informatik
http://informatikforum.bplaced.de/
dort haben Sie auch die Möglichkeit, über Themen der
Grundvorlesungen diskutieren
• Visualisierung zahlreicher Algorithmen aus der Vorlesung
• Das Dijkstra-Archiv
• Informationen zu LATEX
Isolde Adler
Datenstrukturen 2010
2/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Übungsgruppe 9
• Mittwochs 12-14 Uhr (statt 8-10). Nächster Termin: 19.5.2010
• in Raum SR 9 im EG in diesem Gebäude
• Leitung: Herr Maziar Behdju
• Sie können gerne noch zu Herrn Behdju wechseln!
Isolde Adler
Datenstrukturen 2010
3/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Zusammenfassung der letzten Vorlesungsstunde
• verschiedene Graph-Implementierungen:
• Adjazenzmatrix (Kantenfrage in konstanter Zeit)
• Adjazenzliste (Nachbarn und Wege schnell, passt sich an Größe des
Graphen an)
• Labyrinthe – Tiefensuche für ungerichtete und gerichtete Graphen
• Laufzeit O(|V | + |E |)
• Anwendungen: Test auf (starken) Zusammenhang/Kreisfreiheit,
topologische Sortierung
• Breitensuche für ungerichtete und gerichtete Graphen
• Zeit O(|V | + |E |)
• Anwendungen: kürzeste Wege
• Animationen: Breitensuche und Tiefensuche
• Prioritätswarteschlangen und Heaps
Isolde Adler
Datenstrukturen 2010
4/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Ausblick:
• Datenstruktur für Prioritätswarteschlangen
• Die Klasse heap
• Heapsort – eines der schnellsten Sortierverfahren!
Datenstrukturen für Algorithmen:
• Das Kürzeste-Wege-Problem mit Kantengewichten: Dijkstras
Algorithmus
• Berechnen minimaler Spannbäume: Prims Algorithmus, Kruskals
Algorithmus
Isolde Adler
Datenstrukturen 2010
5/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Prioritätswarteschlangen
Der abstrakte Datentyp Prioritätswarteschlange“: Füge Elemente (mit
”
Prioritäten) ein und entferne jeweils das Element höchster Priorität.
Der abstrakte Datentyp Prioritätswarteschlange“ umfasst dann die
”
Operationen
• void insert(x,Priorität),
• int delete max(),
• void change priority(wo,Priorität∗ ), wähle Priorität∗ als neue
Priorität
• und void remove(wo), entferne das durch wo beschriebene Element.
Wir müssen eine geeignete Datenstruktur entwerfen.
Isolde Adler
Datenstrukturen 2010
6/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Der Heap
Ein Binärbaum mit Heap-Struktur ist ein fast vollständiger binärer Baum:
Alle Knoten links von v haben zwei Kinder, alle Knoten rechts von v
haben keine Kinder.
Isolde Adler
Datenstrukturen 2010
7/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Heap-Struktur: Beispiele
n
Der Baum
n
n
n
@
@
@
@
@
@
n
n
HH
H
n
n
und
n
n
n
hat Heap-Struktur ebenso wie
n
n n
Der Baum
Isolde Adler
n
n
HH
H
n
@
@
n
HH
H
n n
@
@
n
hingegen hat keine Heap-Struktur.
n
Datenstrukturen 2010
.
n
8/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Heap-Ordnung
Ein geordneter binärer Baum T mit Heap-Struktur speichere für jeden
Knoten v die Priorität p(v ) von v .
T hat Heap-Ordnung, falls für jeden Knoten v und für jedes Kind w von
v
p(v ) ≥ p(w )
gilt.
• Die höchste Priorität wird stets an der Wurzel gespeichert.
Für die Operation delete max() muss nur die Priorität der Wurzel
überschrieben werden.
• Wie sollte man einen Baum mit Heap-Struktur implementieren? Wir
arbeiten mit einem Array.
Isolde Adler
Datenstrukturen 2010
9/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Datenstruktur Heap
Das Array H ist ein Heap für T , wenn T Heap-Struktur und
Heap-Ordnung hat. Zusätzlich muss gelten
• H[1] = p(r ) für die Wurzel r von T und
• wenn H[i] die Priorität des Knoten v speichert, dann gilt
H[2 · i] = p(vL ) für das linke Kind vL von v und H[2 · i + 1] = p(vR )
für das rechte Kind vR .
Zum Beispiel
3n
Isolde Adler
4n
@
@
9n
@
@
besitzt den Heap (9, 4, 7, 3, 1).
7n
1n
Datenstrukturen 2010
10/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Funktion Insert
• Wie navigiert man in einem Heap H? Wenn Knoten v in Position i
gespeichert ist,
dann ist das linke Kind vL in Position 2 · i, das rechte Kind in
Position 2 · i + 1 und der Vater von v in Position bi/2c gespeichert.
• Wenn wir die Priorität p einfügen wollen, liegt es nahe, p auf der
ersten freien Position abzulegen. Wir setzen also H[++n] = p.
• Der neue Baum hat Heap-Struktur,
• aber die Heap-Ordnung ist möglicherweise verletzt.
Wie kann die Heap-Ordnung kostengünstig repariert werden?
Isolde Adler
Datenstrukturen 2010
11/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Wir fügen die Priorität 11 ein
9m
HH
H
Die Heap-Ordnung ist verletzt und 11 rutscht
7m
3m
···
···
@
m
11
2m
5m 1m
9m
HH
H
Ein weiterer Vertauschungsschritt
nach oben:
7m
11m
@
@
2m
5m 1m
3m
11m
HH
H
repariert die Heap-Ordnung
7m
9m
@
@
2m
5m 1m
3m
Isolde Adler
Datenstrukturen 2010
12/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Repair up Prozedur
Die Klasse heap enthalte die Funktion repair up.
void heap::repair up (int wo){
int p = H[wo];
while ((wo > 1) && (H[wo/2] < p)){
H[wo] = H[wo/2];
wo = wo/2; }
H[wo] = p;}
Wir verschieben die Priorität solange nach oben, bis
• entweder die Priorität des Vaters mindestens so groß ist
• oder bis wir die Wurzel erreicht haben.
Wie groß ist der Aufwand? Höchstens proportional zur Tiefe des Baumes!
Isolde Adler
Datenstrukturen 2010
13/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Funktion Delete max()
H repräsentiere einen Heap mit n Prioritäten. Für delete max:
• gib die Priorität H[1] zurück
• Überschreibe die Wurzel H[1] mit H[n]
• und erniedrige n um 1.
• Durch das Überschreiben mit H[n] ist das entstandene Loch an der
Wurzel verschwunden:
Die Heap-Struktur ist wiederhergestellt.
• Allerdings ist die Heap-Ordnung möglicherweise verletzt und muss
repariert werden.
Die Prozedur repair up versagt: sie ist nur anwendbar, wenn die
falsch stehende Priorität größer als die Vater-Priorität ist.
Isolde Adler
Datenstrukturen 2010
14/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Ein Beispiel
Vorher
1m
HH
HH
H
H
und nachher
5m
4m
5m
4m
@
@
3m
2m
3m
2m 1m
Repariere die Heap-Ordnung: Vertausche mit größtem Kind,
5m
5m
HH
HH
H
H
wiederhole
und fertig.
1m
4m
3m
4m
@
@
3m
2m
1m
2m
Repariere die Heap-Ordnung nach unten.
Isolde Adler
Datenstrukturen 2010
15/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Prozedur Repair down
Die Klasse heap enthalte die Funktion repair down.
void heap::repair down (int wo){
int kind; int p = H[wo];
while (wo <= n/2){
kind = 2 * wo;
if ((kind < n) && (H[kind] < H[kind + 1])) kind ++;
if (p >= H[kind]) break;
H[wo] = H[kind]; wo = kind; }
H[wo] = p; }
• Die Priorität p wird mit der Priorität des größten Kinds“ verglichen
”
und möglicherweise vertauscht. Die Prozedur endet, wenn wo die
richtige Position ist, bzw. wenn wo ein Blatt beschreibt.
• Wie groß ist der Aufwand? Höchstens proportional zur Tiefe.
Animation
Isolde Adler
Datenstrukturen 2010
16/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Change priority und Remove
void change priority(int wo, int p):
• Wir aktualisieren die Priorität, setzen also H[wo] = p.
• Aber wir verletzen damit möglicherweise die Heap-Ordnung!
• Wenn die Priorität angewachsen ist, dann rufe repair up auf.
• Ansonsten hat sich die Priorität verringert und repair down ist
aufzurufen.
void remove(int wo):
• Stelle die Heap-Struktur durch H[wo] = H[n--]; wieder her
• und rufe dann change priority auf.
Alle vier Operationen insert, delete max, change priority und remove
benötigen Zeit höchstens proportional zur Tiefe des Heaps.
Isolde Adler
Datenstrukturen 2010
17/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Tiefe eines Heaps mit n Knoten
Der Binärbaum T besitze Heap-Struktur.
• Wenn T die Tiefe t besitzt, dann hat T mindestens
1 + 21 + 22 + . . . + 2t−1 + 1 = 2t Knoten
• aber nicht mehr als 1 + 21 + 22 + . . . + 2t−1 + 2t = 2t+1 − 1 Knoten.
• Also folgt 2Tiefe(T ) ≤ n < 2Tiefe(T )+1 .
Tiefe (T ) = blog2 nc und alle vier Operationen werden somit in
logarithmischer Zeit unterstützt!
Isolde Adler
Datenstrukturen 2010
18/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Heapsort
Ein Array (A[1], . . . , A[k]) ist zu sortieren.
for (i=1; i <= k; i++)
insert(A[i]);
for (n=k; n >= 1; n--)
A[n] = delete max( );
// Das Array A ist jetzt aufsteigend sortiert.
• Zuerst wird n Mal eingefügt und dann n Mal das Maximum entfernt.
• Sowohl die anfängliche Einfügephase wie auch die letztliche
Entfernungsphase benötigen Zeit höchstens O(n · log2 n).
Heapsort ist eines der schnellsten Sortierverfahren. Die anfängliche
Einfügephase kann sogar noch weiter beschleunigt werden!
Isolde Adler
Datenstrukturen 2010
19/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Wie kann der Heap schneller geladen werden?
Führe statt vielen kleinen Reparaturen eine große Reparatur durch.
• Lade den Heap ohne Reperaturen
• Beginne die Reparatur mit den Blättern. Jedes Blatt ist schon ein
Heap und eine Reparatur ist nicht notwendig.
• Wenn t die Tiefe des Heaps ist, dann kümmern wir uns als nächstes
um die Knoten v der Tiefe t − 1.
• Sei Tv der Teilbaum mit Wurzel v .
• Tv ist nur dann kein Heap, wenn die Heap-Ordnung im Knoten v
verletzt ist: Repariere mit repair down, gestartet in v .
• Höchstens ein Vertauschungsschritt wird benötigt.
• Wenn v ein Knoten der Tiefe t − j ist, dann muss höchstens die
Heap-Ordnung im Knoten v reparariert werden. Höchstens j
Vertauschungsschritte genügen.
Es gibt nur wenige teure Reparaturschritte!
Isolde Adler
Datenstrukturen 2010
20/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Analyse
• Es gibt 2t−j Knoten der Tiefe t − j (für j ≥ 1).
• Für jeden dieser Knoten sind höchstens j Vertauschungsschritte
P
t
durchzuführen, für alle Knoten ist dies also durch j=1 j · 2t−j
beschränkt.
Pt
t−j
• Behauptung:
= 2t+1 − t − 2. Wir geben einen
j=1 j · 2
induktiven Beweis:
t+1
X
j · 2t+1−j
=
j=1
2
t
X
j · 2t−j + t + 1
j=1
=
2 · (2t+1 − t − 2) + t + 1
=
2t+2 − (t + 1) − 2.
Der Heap kann in linearer Zeit geladen werden.
Isolde Adler
Datenstrukturen 2010
21/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Klasse heap
class heap{
private:
int *H; // H ist der Heap.
int n; // n bezeichnet die Größe des Heaps.
void write (int i) { H[++n] = i; }
void repair up (int wo);
void repair down (int wo);
public:
heap (int max) // Konstruktor.
{ H = new int[max]; n = 0; }
int read (int i) { return H[i]; }
void insert (int priority);
int delete max( );
void change priority (int wo, int p);
void remove(int wo);
void build heap(int *A, int k);
void heapsort(int *A, int k);};
Isolde Adler
Datenstrukturen 2010
22/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Prioritätswarteschlangen: Zusammenfassung
(a) Ein Heap mit n Prioritäten unterstützt jede der Operationen insert,
delete max, change priorityund remove in Zeit O(log2 n).
• Für die Operationen change priority und remove muss die
Position der zu ändernden Priorität bestimmt werden.
(b) build heap baut einen Heap mit n Prioritäten in Zeit O(n).
(c) heapsort sortiert n Zahlen in Zeit O(n log2 n).
Isolde Adler
Datenstrukturen 2010
23/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Das Single-Source-Shortest-Path-Problem
Ein gerichteter Graph G = (V , E ) und eine Längen-Zuweisung
länge: E → R≥0 an die Kanten des Graphen ist gegeben.
Bestimme kürzeste Wege von einem ausgezeichneten Startknoten s ∈ V
zu allen Knoten von G .
• Die Länge eines Weges ist die Summe seiner Kantengewichte.
• Mit Hilfe der Breitensuche können wir kürzeste-Wege Probleme
lösen, falls länge(e) = 1 für jede Kante e ∈ E gilt. Für allgemeine
nicht-negative Längen brauchen wir eine ausgeklügeltere Idee.
• Kantengewichte sind nicht-negativ: Die kürzeste, mit s inzidente
Kante (s, v ) ist ein kürzester Weg von s nach v .
• Dijkstras Algorithmus setzt diese Beobachtung wiederholt ein.
Isolde Adler
Datenstrukturen 2010
24/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Dijkstras Algorithmus
(1) Setze S = {s} und
länge (s, v ) wenn
distanz[v] =
∞
sonst.
(s, v ) ∈ E
/* distanz[v] ist die Länge des bisher festgestellten kürzesten Weges
von s nach v .
*/
(2) Solange S 6= V wiederhole
(a) wähle einen Knoten w ∈ V − S mit kleinstem Distanz-Wert.
/* distanz[w] ist die tatsächliche Länge eines kürzesten Weges
von s nach w .
(b) Füge w in S ein.
(c) Aktualisiere die Distanz-Werte der Nachfolger von w :
Setze für jeden Nachfolger u ∈ V \ S von w
c = distanz[w] + länge(w,u);
distanz[u] = (distanz[u] > c) ? c : distanz[u];
Isolde Adler
Datenstrukturen 2010
25/35
*/
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Datenstrukturen für Dijkstras Algorithmus
In der Vorlesung Algorithmentheorie“ wird gezeigt, dass Dijkstras
”
Algorithmus korrekt ist und das Kürzeste-Wege-Problem effizient löst.
• Darstellung des Graphen G : Wir implementieren G als Adjazenzliste,
da wir dann sofortigen Zugriff auf die Nachfolger u von w im
Aktualisierungschritt (2c) haben.
• Implementierung der Menge V \ S:
• Knoten sind gemäß ihrem anfänglichen Distanzwert einzufügen.
• Ein Knoten w mit kleinstem Distanzwert ist zu bestimmen und zu
entfernen.
Wähle einen Min-Heap, um die entsprechende Prioritätswarteschlange zu implementieren:
• Ersetze die Funktion delete max() durch die Funktion
delete min().
• Implementiere den Aktualisierungschritt durch
change priority(wo, c). Woher kennen wir die Position wo?
Isolde Adler
Datenstrukturen 2010
26/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Minimale Spannbäume
Sei G = (V , E ) ein ungerichteter, zusammenhängender Graph.
Jede Kante e ∈ E erhält eine reellwertige Länge länge(e)“.
”
• Ein Baum T = (V 0 , E 0 ) heißt ein Spannbaum für G , falls V 0 = V
und E 0 ⊆ E .
• Die Länge eines Spannbaums ist die Summe der Längen seiner
Kanten.
• Ein minimaler Spannbaum ist ein Spannbaum minimaler Länge.
• Je zwei Knoten von G bleiben auch in einem Spannbaum
miteinander verbunden, denn ein Baum ist zusammenhängend.
Wenn wir aber irgendeine Kante entfernen, dann zerstören wir den
Zusammenhang.
• Wenn alle Kantenlängen nicht-negativ sind, dann suchen wir nach
einem zusammenhängenden Teilgraph von G minimaler Länge. Web
Isolde Adler
Datenstrukturen 2010
27/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Der Algorithmus von Prim: Die Idee
• Angenommen wir wissen, dass ein Baum B in einem minimalen
Spannbaum enthalten ist.
• Wir möchten eine kreuzende Kante zu B hinzufügen: e soll also
einen Knoten in B mit einem Knoten außerhalb von B verbinden.
• Der Algorithmus von Prim wählt eine kürzeste kreuzende Kante.
• In der Vorlesung Algorithmentheorie“ wird gezeigt, dass auch
”
B ∪ {e} in einem minimalen Spannbaum enthalten ist:
Der Algorithmus berechnet also einen minimalen Spannbaum.
• Worauf müssen wir bei der Implementierung achten?
• Eine kürzeste kreuzende Kante muss schnell gefunden werden.
• Wenn der Baum B um einen neuen Knoten u anwächst, dann
erhalten wir neue kreuzende Kanten, nämlich in u endende Kanten.
Isolde Adler
Datenstrukturen 2010
28/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Der Algorithmus von Prim
(1) Setze S = {1}.
/* B ist stets ein Baum mit Knotenmenge S. Zu Anfang besteht B
nur aus dem Knoten 1.
(2) Solange S 6= V , wiederhole:
(a) Bestimme eine kürzeste kreuzende Kante e = {u, v }.
(b) Füge e zu B hinzu.
(c) Wenn u ∈ S, dann füge v zu S hinzu. Ansonsten füge u zu S hinzu.
/* Beachte, dass wir neue kreuzende Kanten erhalten, nämlich alle
Kanten die den neu hinzugefügten Knoten als einen Endpunkt und
einen Knoten aus V \ S als den anderen Endpunkt besitzen.
Isolde Adler
Datenstrukturen 2010
29/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Datenstruktur für Prims Algorithmus
• Für jeden Knoten u ∈ V \ S bestimmen wir die Länge l(u) einer
kürzesten Kante, die u mit einem Knoten in S verbindet.
• Wir verwalten die Knoten in V \ S mit einer Prioritätswarteschlange
und definieren l(u) als die Priorität des Knoten u.
• Initialisiere einen Min-Heap, indem jeder Nachbar u von 1 mit
Priorität länge({1, u}) einfügt wird, bzw. mit Priorität ∞, wenn u
kein Nachbar ist.
• Wir bestimmen also eine kürzeste kreuzende Kante, wenn wir einen
Knoten in u ∈ V \ S mit niedrigster Priorität bestimmen.
• Beachte, dass sich nur die Prioritäten der Nachbarn von u ändern.
• Implementiere G durch eine Adjazenzliste, da wir stets nur auf die
Nachbarn eines Knoten zugreifen müssen.
Isolde Adler
Datenstrukturen 2010
30/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Kruskals Algorithmus: Die Idee
• Prim lässt einen minimalen Spannbaum Kante für Kante“ wachsen.
”
• Kruskals Algorithmus beginnt mit einem Wald von Einzelknoten.
• Die Kanten werden nach aufsteigender Länge sortiert und der Reihe
nach, beginnend mit Kanten kürzester Länge verarbeitet.
• Wenn die Kante e dran“ ist und keinen Kreis schließt, dann wird die
”
Kante zum Wald hinzugefügt.
• Ansonsten schließt die Kante einen Kreis und wird verworfen.
Wie stellt man fest, ob eine Kante einen Kreis schließt?
Isolde Adler
Datenstrukturen 2010
31/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Kruskals Algorithmus
(1) Sortiere die Kanten gemäß aufsteigender Länge. Sei W = (V , F ) der
leere Wald, also F = ∅.
(2) Solange W kein Spannbaum ist, wiederhole
(a) Nimm die gegenwärtig kürzeste Kante e und entferne sie aus der
sortierten Folge.
(b) Verwerfe e, wenn e einen Kreis in W schließt.
(c) Ansonsten setze F = F ∪ {e}: e wird zum Wald W hinzugefügt.
Wir beschränken uns auf die Implementierung.
In der Vorlesung Algorithmentheorie“ wird gezeigt, dass Kruskals
”
Algorithmus korrekt ist.
Isolde Adler
Datenstrukturen 2010
32/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Union-Find Datenstruktur I
• Wir sortieren die Kanten zum Beispiel mit Heapsort.
• Danach müssen wir für alle Kanten e = {u, v } entscheiden,
ob e einen Kreis in W schließt.
• Die Operation find(u) bestimme die Wurzel wu des Baumes,
der u enthält.
• Die Kante e schließt genau dann einen Kreis, wenn
find(u) = find(v ).
• Wenn e keinen Kreis in W schließt, dann müssen wir die Bäume mit
den Wurzeln find(u) und find(v ) vereinigen. Dazu benutzen wir die
Operation union(u, v ).
Wie sollten wir den Wald W implementieren?
Isolde Adler
Datenstrukturen 2010
33/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Union-Find Datenstruktur II
Wir implementieren den Wald W durch ein Vater-Array.
• Zu Anfang ist Vater[i] = i für alle Knoten i. (Wir fassen i immer
dann als eine Wurzel auf, wenn Vater[i] = i gilt.)
• Wie ist find(u) zu implementieren?
• Klettere den Baum von u mit Hilfe des Vater-Arrays hoch.
• Die Kletter-Zeit“ ist durch die Tiefe des Baumes beschränkt.
”
• Wie garantieren wir, dass die Bäume nicht zu tief werden?
• Wenn wir zwei Bäume vereinigen, dann hänge die Wurzel des
kleineren Baumes unter die Wurzel des größeren Baumes! Achtung:
hierbei wir eine Kante eingefügt, die wir möglicherweise nicht zu W
hinzufügen!
• Betrachte einen beliebigen Knoten v .
• Die Tiefe vergrößert sich nur dann um 1, wenn v dem kleineren
Baum angehört. Wenn die Tiefe von v um 1 anwächst, dann wird
sich der Baum von v in seiner Größe mindestens verdoppeln.
• Also ist die Tiefe aller Bäume durch log2 (|V |) beschränkt.
Isolde Adler
Datenstrukturen 2010
34/35
Wiederholung
Kapitel 3: Elementare Datenstrukturen
Prioritätswarteschlangen
Datenstrukturen und Algorithmen
Die Union-Find Datenstruktur: Das Fazit
Ein Union-Schritt benötigt nur konstante Zeit, während ein Find-Schritt
höchstens logarithmische Zeit benötigt.
• Mit der Union-Operation modifizieren wir den Wald!
• Wir benötigen zwei Datenstrukturen, nämlich
• die Union-Find Datenstruktur und
• eine zweite Datenstruktur, die die Kanten des minimalen
Spannbaums abspeichert.
Damit hat Kruskals Algorithmus eine Laufzeit von O(|E | · log |V |)
Isolde Adler
Datenstrukturen 2010
35/35
Herunterladen