Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS 06 23.5.
-
Upload
bathild-kenagy -
Category
Documents
-
view
108 -
download
2
Transcript of Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS 06 23.5.
Effiziente Algorithmen
Hartmut KlauckUniversität FrankfurtSS 0623.5.
Minimale Spannbäume
Definition In einem ungerichteten,
zusammenhängenden Graphen G heisse eine Teilmenge von Kanten ein spannender Baum, wenn
• Die Kanten einen Baum bilden• Jeder Knoten von G in dem Baum liegt
Wenn die Kanten von G mit nichtnegativen Gewichten belegt sind ist ein minimaler Spannbaum ein spannender Baum mit minimaler Summe der Kantengewichte
Minimale Spannbäume
Motivation: Maß für Verbindungskosten in Netzwerken Verlege Kabel etc. an den Kanten des
minimalen Spannbaums Problem wurde zuerst von Boruvka 1926
untersucht
Weitere Algorithmen: Kruskal, Prim
Eingabeformat: Adjazenzliste mit Gewichten
Minimale Spannbäume
Generischer Algorithmus: Fange an mit leerer Menge von Kanten Füge Kanten ein, wobei die aktuelle
Kantenmenge immer eine Teilmenge eines minimalen Spannbaums ist
Eine Kante, die so eingefügt werden kann, nennen wir sicher
Generischer Algorithmus
Setze A=; Solange wie A noch kein spannender
Baum ist, finde eine sichere Kante e und füge sie ein
Ausgabe A
Sichere Kanten
Schwierigkeit besteht darin, sichere Kanten zu finden
Definition: Ein Schnitt S, V-S ist eine Partition der
Knotenmenge V Eine Kantenmenge respektiert den Schnitt,
wenn keine der Kante den Schnitt kreuzt Eine Kante heisst leicht für einen Schnitt, wenn
sie die Kante mit kleinstem Gewicht ist, welche den Schnitt kreuzt
Eine Kante heisst leicht, wenn sie leicht für eine Menge von Schnitten ist (z.B. alle Schnitte, die A respektiert)
Sichere Kanten
Theorem 11.1:Sei G ungerichtet, zusammenhängend, mit Kantengewichten. Sei A eine Teilmenge eines minimalen Spannbaums in G. Sei (S, V-S) irgendein Schnitt, den A respektiert. Dann ist eine leichte Kante e für (S, V-S) auch sicher.
Beweis: Sei T ein minimaler Spannbaum, der A enthält T enthalte e nicht (sonst sind wir fertig) Wir konstruieren einen anderen Spannbaum,
der A und e enthält, und ebenfalls minimal ist.
Sichere Kanten
Die Kante e={u,v} , in T eingefügt ergibt einen Kreis p in T[{e}.
u und v liegen auf verschiedenen Seiten des Schnitts
Es gibt also noch eine Kante e‘ in T, die den Schnitt kreuzt.
e‘ liegt nicht in A, da A den Schnitt respektiert Entferne e‘, dadurch bricht T in zwei Teile Zufügen von e verbindet T wieder, zu einem Baum
T‘ W(e)=W(e‘) für die Gewichtsfunktion W, daher ist T‘
minimal Somit ist A[ {e} eine Teilmenge von T ‘ D.h. e ist sicher für A
Welche Kanten liegen nicht in min. Spannbäumen? Theorem 11.2:
G sei ein Graph mit Gewichten W.Seien alle Kantengewichte unterschiedlich.Sei C ein Kreis in G und e={u,v} die teuerste Kante in C. Dann liegt C in keinem minimalen Spannbaum in G.
Beweis: Angenommen e liegt auf einem minimalen
Spannbaum T Entferne e aus T Wir erhalten zwei Bäume Die Knoten der Bäume bilden einen Schnitt in G Folge C-{e} von u nach v Dieser Weg kreuzt irgendwann den Schnitt mit einer
Kante e‘ T-{e}[{e‘} ist ein Spannbaum mit geringerem
Gewicht als T, Widerspruch
Algorithmen
Wir füllen zunächst das Skelett des generischen Algorithmus‘ auf zwei Arten Prim: A ist immer ein Baum Kruskal: A ist ein Wald (Menge von
Bäumen), der „zusammenwächst“
Datenstruktur Union-Find
Wir verwenden eine Datenstruktur für Mengen mit den folgenden Operationen: Make-Set(v):
erzeugt eine Menge {v}, indiziert durch v
Find-Set(v):zu einem Element v finde den Index der Menge, die es enthält
Union(u,v):Als Ergebnis ist die Vereinigung der Mengen, die durch u und v indiziert sind jetzt mit u oder mit v indiziert
Kruskal
1. Eingabe: Graph G, Gewichte W2. A=;3. Für jeden Knoten v
a) Make-Set(v)4. Sortiere die Kanten in E aufsteigend nach
Gewicht5. Für jede Kante (u,v), aufsteigend nach Gewicht
a) Wenn Find-Set(u) Find-Set(v), dannA:=A[ {(u,v)}
b) Union (u,v)6. Ausgabe A
Implementierung Union Find Einfache Implementierung der Datenstruktur Universum mit n Elementen
Array M mit n Einträgen Mengen sind durch Bäume repräsentiert, als
Pointer zur Wurzel im Array gespeichert. MakeSet(v) für alle v: M(v)=v für alle v Union(u,v): Setze M(v)=u, wenn die Menge von u
grösser als die Menge von v ist. Find(v): Folge den Pointern ab M(v), bis M(u)=u
erreicht, gebe u aus Zusätzlich speichern wie für jeden Knoten, der
eine Wurzel ist die Grösse seiner Menge in einem Array G(v), bei Union entsprechend update
Laufzeiten Union Find
MakeSet: O(n) insgesamt Union: O(1) Find: entspricht maximaler Tiefe der Bäume Tiefe ist O(log n): Behauptung:
Bei Grösse g ist die Tiefe · log g:Beweis: Zu Beginn klar.Wenn Menge von u und Menge von v mit Grössen a und b und Tiefen q· log a und r· log b zusammenkommen:Neuer Baum hat Grösse a+b Gelte O.B.d.A. a · b. 3 Fälle:
• r < q, dann neue Tiefe q · log a · log (a+b)• r = q, dann neue Tiefe q+1, aber a¸ 2q, b¸ 2q, a+b¸
2r+2q=2q+1, also neue Tiefe · log (a+b)• r>q, es gilt a¸ b¸ 2r, neue Tiefe ist r+1, a+b¸ 2r+1, also
neue Tiefe · log (a+b)
Kruskal
1. Eingabe: Graph G, Gewichte W2. A=;3. Für jeden Knoten v
a) Make-Set(v)4. Sortiere die Kanten in E aufsteigend nach
Gewicht5. Für jede Kante (u,v), aufsteigend nach Gewicht
a) Wenn Find-Set(u) Find-Set(v), dannA:=A[ {(u,v)}
b) Union (u,v)6. Ausgabe A
Laufzeit Kruskal
Wir erhalten so: bis 3: O(n) 4: O(m log n) 5: O(m log n)
Insgesamt O(n+m log n)
Korrektheit
Wir müssen nur zeigen, dass die Kanten, die eingefügt werden immer sicher sind. Wähle einen Schnitt, der A respektiert,
und den die neue Kante kreuzt Neue Kante ist Kante mit minimalen
Gewicht unter allen Kanten, die noch keinen Kreis bilden
Also ist neue Kante sicher.
Prim
In Prim‘s Algorithmus bilden Kanten in A immer einen Baum
Wir verwenden eine Prioritätswarteschlange wie in Dijkstra: Operationen:
• Init: initialisiert Datenstruktur• ExtractMin: Entfernt minimalen Schlüssel• DecreaseKey(v,k): Verringere einen Schlüssel
Einfache Implementierung mit Heap:• Init: O(n)• Extract Min: O(log n)• DecreaseKey: O(log n)
Prim
Eingabe: Graph G, Gewichte W, Wurzel r Ausgabe: minimaler Spannbaum als Array
A={(v, (v)): v=1,…,n} von Vorgängern1. Für alle v2 V setze key(v)=1
und (v)=NIL2. key(r)=03. Init: Bilde Priority Queue Q4. Während Q nichtleer:
a) u=ExtractMinb) Für alle Nachbarn v von u:
i. Wenn v in Q liegt, und key(v) > W(u,v) dann(v)=u und key(v):=W(u,v)
Laufzeit Prim
Einmal Init, n mal ExtractMin und m mal DecreaseKey
Insgesamt O( (n+m) log n) bei Heap Implementierung
Prioritätswarteschlange kann auch so implementiert werden, dass m DecreaseKey Operationen O(m) Zeit brauchen [amortisierte Analyse]
Dann Laufzeit O(n log n +m) Insbesondere, wenn m¸ n log n, dann
Linearzeit
Korrektheit
Es gilt: A bildet immer einen Baum Für Knoten v in Q entspricht key(v) dem Gewicht
einer leichten Kante, die in den Baum A führt (wenn key(v)<1)
Zu Beginn ist dies wahr Die Einfügung von r ist korrekt Wenn u eingefügt wird ist key (u) nach IV eine leichte
Kante, d.h. sicher Zusätzlich bildet A Baum, und u noch nicht in A, also
nach Zufügung der Kante nach u immer noch Die Nachbarn v von u werden durchlaufen, wenn key(v)·
1, dann ist key(v) Gewicht einer leichten Kanten nach A-{u}, ist eine Kanten von v nach u besser: update, d.h. nachher gilt IV