Datenstrukturen & Algorithmen Lösungen zu Blatt 9 FS 15

Eidgenössische
Technische Hochschule
Zürich
Ecole polytechnique fédérale de Zurich
Politecnico federale di Zurigo
Federal Institute of Technology at Zurich
Institut für Theoretische Informatik
Peter Widmayer
Tobias Pröger
Thomas Tschager
Datenstrukturen & Algorithmen
Lösung 9.1
29. April 2015
Lösungen zu Blatt 9
FS 15
Tiefensuche, Breitensuche und Topologische Sortierung.
a) A, B, C, I, F, D, E, H, G
b) A, B, C, D, E, H, I, F, G
c) Sowohl Breiten- als auch Tiefensuche müssen für jeden Knoten einmal alle Nachbarn besuchen. Ist der Graph durch Adjazenzlisten gegeben, so muss die Liste der Nachbarn für
jeden Knoten abgearbeitet werden. Die Laufzeit ist in diesem Fall O(n + m), also für zusammenhängende Graphen O(m) (wie üblich bezeichnen wir die Anzahl Knoten mit n und
die Anzahl Kanten mit m).
Wenn allerdings nur eine Adjazenzmatrix gespeichert ist, kann man die Nachbarn eines
Knotens nur finden, indem man alle Einträge der entsprechenden Zeile durchgeht. Da dies
für jeden Knoten getan werden muss, ist die Laufzeit Θ(n2 ).
Bei einem sehr dichten Graphen mit m ∈ Θ(n2 ) ist die asymptotische Laufzeit gleich. Bei
dünnen Graphen, beispielsweise mit m ∈ O(n), führt die Verwendung einer Adjazenzmatrix allerdings zu einer erheblich schlechteren asymptotischen Laufzeit.
d) Eine kleinste Möglichkeit ist die Entfernung der Kanten (E, A) und (F, B). Eine mögliche
topologische Sortierung ist A, B, C, I, H, D, F, G, E (die topologische Sortierung ist nicht
eindeutig).
Die andere kleinste Möglichkeit besteht in der Entfernung der Kanten (A, B) und (F, B).
Eine mögliche topologische Sortierung wäre dann B, H, D, G, E, A, C, I, F (auch hier ist
die topologische Sortierung nicht eindeutig).
Es existieren zahlreiche weitere Möglichkeiten, mehr als zwei Kanten zu entfernen. Insbesondere könnte sogar E 0 = E gewählt werden. In diesem Fall ist der entstehende Graph
leer, und jede Reihenfolge der Knoten bildet eine topologische Sortierung.
Lösung 9.2
Union-Find Strukturen.
Wenn jeweils der Baum mit weniger Knoten an denjenigen mit mehr Knoten angehängt wird,
dann gilt für die Union-Find Struktur für jeden Baum mit Höhe h und n Knoten die Invariante
n ≥ 2h (Lemma 6.3, Kapitel 6.2.2).
Die Invariante besagt, dass ein Baum der Höhe h mindestens 2h Knoten enthalten muss. Wir
konstruieren einen Baum der Höhe h und genau 2h Knoten wie folgt: Ein Baum der Höhe h = 0
besteht aus n = 1 = 20 Knoten. Um einen Baum der Höhe h > 0 zu konstruieren, verschmelzen
wir zwei Bäume der Höhe h−1 mit je genau 2h−1 Knoten. Da der eine in den anderen eingehängt
wird, wächst die Höhe um eins. Somit hat der neue Baum genau Höhe h und 2·2h−1 = 2h Knoten.
Die Anzahl benötigter Union-Operationen ist durch folgende rekursive Gleichung gegeben:
u(0) = 0, u(h) = 2 · u(h − 1) + 1.
(1)
Damit ist die Anzahl benötigter Union-Operationen genau u(h) =
Ph
i=1 2
i−1
= 2h − 1.
Mit weniger Operationen kann man unmöglich einen Baum mit 2h Knoten erzeugen, da für
jeden zusätzlichen Knoten im Baum mindestens eine Union-Operation nötig ist. Da ein Baum
der Höhe h auch mindestens 2h Knoten enthalten muss, ist es unmöglich eine Höhe von h mit
weniger als 2h − 1 Operationen zu erreichen.
Lösung 9.3
Minimale Spannbäume.
a) Das Verfahren von Kruskal berechnet den folgenden minimalen Spannbaum.
A
4
6
3
1
B
D
7
2
C
F
4
3
5
E
5
1
G
b) Wir beweisen die Aussage durch vollständige Induktion über die Knotenanzahl |V |.
Induktionsverankerung (|V | = 1): Ein Graph mit genau einem Knoten hat keine Kante,
also muss |E| = 0 ≤ 1 − 1 = |V | − 1 gelten.
Induktionsannahme: Angenommen, jeder ungerichtete kreisfreie Graph mit genau |V | − 1
Knoten hat höchstens |V | − 2 Kanten.
Induktionsschluss (|V | − 1 → |V |): Betrachte nun einen ungerichteten kreisfreien Graphen
G = (V, E). Aufgrund der Kreisfreiheit gibt es mindestens einen Knoten w mit Grad 0 oder
1. Seien nun V 0 := V \{w} und E 0 := {{u, v} ∈ E | u, v ∈ V 0 }. Offenbar ist |V 0 | = |V | − 1
und, da von w höchstens eine einzige Kante ausgeht, |E 0 | ≥ |E| − 1 (d.h., |E| ≤ |E 0 | + 1).
Nach Induktionsvoraussetzung ist |E 0 | ≤ |V 0 | − 1, also erhalten wir
|E| ≤ |E 0 | + 1 ≤ |V 0 | − 1 + 1 = |V 0 | = |V | − 1.
(2)
c) Sei G = (V, E, w) ein ungerichteter Graph, bei dem keine zwei Kanten e, e0 ∈ E das gleiche
Gewicht haben. Angenommen, G hätte zwei minimale Spannbäume T1 = (V, E1 ) und T2 =
(V, E2 ). Die Kanten aus E1 ∩E2 kommen sowohl in T1 als auch in T2 vor. Seien E10 = E1 \E2
und E20 = E2 \E1 die Kanten, die ausschliesslich in T1 bzw. in T2 enthalten sind. Da die
Gewichte aller Kanten paarweise verschieden ist, enthält die Menge E10 ∪· E20 eine eindeutig
bestimmte Kante e⊥ minimalen Gewichts. Sei diese o.B.d.A. in T1 enthalten. Würde sie T2
hinzugefügt, dann enthielte T2 nach Aufgabenteil b) einen Kreis. Dieser enthält mindestens
2
eine Kante e0 ∈ E20 (ansonsten hätte er neben e⊥ ausschliesslich Kanten aus E1 ∩ E2 und
wäre auch in T1 ein Kreis). Wird e0 aus T2 entfernt und stattdessen e⊥ eingefügt, dann
erhalten wir eine Teilmenge von Kanten, die noch immer kreisfrei und zusammenhängend
(also ein Spannbaum) ist, wegen w(e⊥ ) < w(e0 ) aber ein geringeres Gesamtgewicht hat.
Also war T2 kein minimaler Spannbaum, was der Annahme widerspricht.
Lösung 9.4
Schwarze Löcher.
Dieses Problem kann analog zum Problem “Star in einer Menge finden” gelöst werden, welches
in der ersten Vorlesung vorgestellt wurde.
Wir beobachten zunächst, dass es maximal ein schwarzes Loch geben kann: Sei v ein schwarzes
Loch. Nach Definition ist der Ausgangsgrad von v genau 0. Also ist (v, v) ∈
/ E. Da der Eingangsgrad genau |V | − 1 beträgt, gibt es für alle v 0 ∈ V \{v} eine Kante (v 0 , v) ∈ E und der
Ausgangsgrad jedes Knotens v 0 ∈ V \{v} beträgt mindestens 1. Damit kann v 0 kein weiteres
schwarzes Loch sein.
Der Algorithmus besteht aus zwei Phasen. Zunächst finden wir einen Kandidaten v für ein
schwarzes Loch mit |V |−1 Vergleichen. Danach prüfen wir mit 2|V |−1 Vergleichen, ob v wirklich
ein schwarzes Loch ist. Sei G = (V, E) mit V = {v1 , ..., vn } und der zugehörigen Adjazenzmatrix
AG = (aij ) mit aij ∈ {0, 1}, aij = 1 ⇔ (vi , vj ) ∈ E, gegeben. Zur Bestimmung eines Kandidaten
benutzen wir zwei Variablen i und j, die mit i ← 1 und j ← n initialisiert werden. Danach wird
der Eintrag aij geprüft. Ist aij = 0, dann ist (vi , vj ) ∈
/ E und vj sicher kein schwarzes Loch (denn
der Eingangsgrad von vj ist kleiner als n − 1, falls (vj , vj ) ∈
/ E). Also setzen wir j ← j − 1. Ist
dagegen aij = 1, dann ist (vi , vj ) ∈ E und vi kein schwarzes Loch (denn der Ausgangsgrad von
vi ist mindestens 1). Also setzen wir i ← i + 1. Nach n − 1 solchen Vergleichen ist i = j und vi
wird unser Kandidat für ein schwarzes Loch. Nun prüfen wir noch, ob vi wirklich ein schwarzes
Loch ist, indem wir den Eingangsgrad und den Ausgangsgrad von vi berechnen. Dazu müssen
wir lediglich prüfen, ob aij = 0 für j = 1, ..., n und aji = 1 für j = 1, ..., n, j 6= i, sind. Ist dies
der Fall, dann ist vi das gesuchte schwarze Loch. Ansonsten besitzt G kein schwarzes Loch.
Die Korrektheit des Verfahrens folgt aus der Beobachtung, dass die Zeiger i bzw. j nur dann
aktualisiert werden, wenn vi bzw. vj kein schwarzes Loch sind. Ist umgekehrt i so gesetzt, dass
vi ein schwarzes Loch ist, dann ist aij = 0 für alle j = 1, ..., n, also wird i niemals vergrössert
(sondern nur noch j verkleinert). Analog wird j niemals verkleinert, wenn vj ein schwarzes Loch
ist, da in diesem Fall aij = 1 ist für alle i = 1, ..., n, i 6= j.
3