Mitschrift der Vorlesung

Werbung
Algorithmen
17. Juli 2007
Die Vorlesung wurde gehalten im
S OMMERSEMESTER 2007
von
N INA Z WEIG
und
P ROF. D R . M ICHAEL K AUFMANN
Diese Vorlesungsmitschrift wurde angefertigt von:
T ILL H ELGE H ELWIG
Lektorat: Nina Zweig
Diese Mitschrift erhebt keinen Anspruch auf Vollständigkeit. Ich bemühe
mich zwar darum, aber im Endeffekt sind es meine persönlichen Notizen
aus der Vorlesung und kein offizielles Skript. Verbesserungsvorschläge nehme
ich gerne entgegen und freue mich natürlich auch, wenn jemand die
Mitschrift gebrauchen kann und als Gegenleistung vielleicht korrekturliest.
1
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
1
3
ANALYSE VON ALGORITHMEN
Worum geht es?
1. Algorithmendesign
(a)
(b)
(c)
(d)
von der alltagssprachlichen Fragestellung zum mathematisch formalen Problem
Formulierung des Lösungswegs
Korrektheit
Analyse
i. des Laufzeitverhaltens und
ii. des Speicherbedarfs
2. Implementierung
(a) Datenstrukturen
(b) Java, OOP
3. Experimentelle Analyse als Teil des “Algorithm Engineering”
2
Was ist ein Algorithmus?
Nach Donald E. Knuth:
Instanz: konkrete Eingabe I ∈ D für einen Algorithmus
3
Analyse von Algorithmen
• Laufzeit
• Speicherverbrauch
Sei A ein Algorithmus mit D und B und I ∈ D eine Instanz, dann kann die Laufzeit TA (I) berechnet bzw.
gemessen werden.
3.1
Allgemeine Komplexität
1. worst-case-Komplexität:
TA,wc (n) = max {TA (I)| |I| = n}
I∈D
Was ist “n”?
Charakteristische Größe einer Eingabe, z.B. Anzahl der Elemente einer Menge, Größe eines Arrays,
etc.
2. average-case-Komplexität:
P
1
TA,avg (n) = |{I||I|=n
TA (I)
}|
I=D
|I|=n
2
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
3.2
3
ANALYSE VON ALGORITHMEN
Asymptotische Notation
• Implementierung
• Compiler/Interpreter
• Maschinenbefehlssatz
Asymptotische Notation als Betachtung des Funktionsverhaltens für große n. Dazu: Unterteilung des
Algorithmus in elementare Operationen: solche mit “konstanter” Laufzeit, z.B. Zuweisungen, kleinere
Additionen, Inkrementieren, ... Diese haben die Laufzeit O(1).
3.3 O-Notation
“Groß-O” von: O(f (n)) :=Menge von Funktionen g(n), die sich asymptotisch “gleich” verhalten, im Sinne
von:
∃c > 0, ∃n0 , ∀n ≥ n0 : g(n) ≤ c · f (n)
Beispiel: g(n) = 5n2 + 13n + 5
g(n) ∈ O(n2 )?
Ja: f (n) = n2 , ∃c : c = 13 ⇒ n ≥ 3 ⇒ g(n) ≤ 13n2
Anschaulich: O-Notation beschreibt “obere Schranke”.
3.4
O-Notation
“klein-o” von: O(n) ist eine Menge von Funktionen g(n) mit:
∀c> 0, ∃n0 > 0, ∀n ≥ n0 : g(n) ≤ c · f (n)
Beispiel: Ist g(n) ∈O(n2 )?
Nein: c = 1 @n0 , so dass ∀n ≥ n0 : g(n) ≤ c · f (n)
aber: g(n) ∈O(n3 )
Anschaulich: O-Notation beschreibt die “echt größere Schranke”.
3.5 Ω-Notation
“Groß-Omega”: ∃c > 0, ∃n0 > 0, ∀n ≥ n0 : g(n) ≥ c · f (n) “untere Schranke”
3.6 ω-Notation
“klein-omega”: ∀c > 0, ∃n0 > 0, ∀n ≥ n0 : g(n) ≥ c · f (n) “echt kleinere untere Schranke”
3.7 Θ-Notation
“Theta”: Schnittmenge Θ(f (n)) = O(f (n) ∩ Ω(f (n))
3
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Beispiel:
g(n) ∈ O(f (n))
g(n) ∈ Θ(f 0 (n)) ⇔ g(n) ∈ O(f 0 (n)) ∧ g(n) ∈ Ω(f 0 (n))
g(n) ∈ ω(f 00 (n))
Anmerkung: Schreibweise oft: g(n) = O(n2 )
Zurückkommend auf die Notation: O(1)=konstante
ˆ
Laufzeit bedeutet, dass wir die genaue Anzahl von
Rechenschritten nicht kennen (müssen), solange wir annnehmen können, dass sie auf jedem Systen in
“kleiner”, von der Größe des Operanden unabhängige Anzahl von Schritten berechnet werden.
Beispiel: Gleichheit von zwei Objekten
⇒ Zeigervergleich ⇒ elementare Operation
Schwierig: Addition von Integern
⇒ bis zu einer natürlichen Grenze elementar ⇒ danach nicht mehr
4
Suchen
Eingabe: Datenstruktur d mit Menge von Objekten O, deren Menge von Schlüsseln S und ein Schlüssel
h ∈ U.
Ausgabe: Objekt o ∈ d mit o.key == k, wenn o ∈
/ d Rückgabe ’null’.
Konvention: d.get(i) gibt i-tes Element aus d zurück (auch für Arrays - normal A[i]).
4
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Annahme: Elemente der Menge S im Rechner darstellbar ⇒∃f : S ⇒ N, R.
z.B.
Universum U im Folgenden N. Wir benutzen Datenstruktur d mit folgenden Operationen:
• Initialisieren
• Einfügen
• Suchen
Einfache Datenstrukturen: Liste, Array
4.1
Lineare Suche
Sei U = {1, . . . , n}, gesucht ist k ∈ U .
Object o = null;
for Object object in d do
if object.key == k then
o = object;
break;
return o;
Zeile 2 in Java 1.4 (Objekte mit Interface List):
for (Iterator it = d.getIterator(); it.hasNext(); ) {
Object object = it.next();
...
}
Finite Berechnung:
√
Korrektheit: Schleifeninvariante im k-ten Durchlauf: o zeigt auf null, wenn Objekt bisher nicht gefunden, sonst auf Objekt.
Laufzeitanalyse: worst case
Zeilen 1,3-6: konstant
Zeile 2:
O(n)
⇒ Gesamtlaufzeit: O(n)
Laufzeitanalyse: average case
Annahme, dass k ∈ S gleichverteilt ⇒jeder Schlüssel hat gleiche Wahrscheinlichkeit, gesucht zu werden.
n
P
Tlin.Such, avg (n) = n1 i = n(n+1)
2
i=1
Typische Falle beim Programmieren
for (int i = 0; i < d.size(); ++i)
Object object = d.get(i);
Wenn d ist Liste, d.get(i) = O(n) ⇒ worst-case-Laufzeit: O(n2 )
5
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4.2
4
SUCHEN
Binäre Suche
Eingabe: Datenstruktur d enthält Menge von Objekten O mit Schlüsselmenge S, k ∈ S.
Zusicherung: Elemente in d nach ihrem Schlüssel (aufsteigend) sortiert.
Ausgabe: siehe lineare Suche
Idee: Größe der Datenstruktur (des Suchraumes) in jedem Schritt halbieren.
1 Object binarySearch(DataStructure d, int k)
2 if (d.size() == 1)
return (d.get(0).key==k ? d.get(0) : null
3
| {z } );
|
{z
}
| {z
}
false
true
Bedingung
4 if (d.size() == 0)
5
return null;
6 int probeIndex = d.size() / 2;
7 Object probe = d.get(probeIndex);
8 if (probe.key == k)
9
return probe;
10 else
11
return (probe.key > k ? // k liegt “vor” probe
12
binarySearch(d.firstHalf(), k) :
13
binarySearch(d.secondHalf(), k));
Finitheit:√ Datenstrukturgröße wird in jedem Schritt halbiert. Für d.size() ∈ {0, 1} wird Rückgabe erzwungen.
Korrektheit: Durch Sortierung kann k nur in der beibehaltenen Hälfte liegen.
Laufzeitanalyse:
Zeilen 1-6: O(1)
Zeile 7:
O(1) für Array
O(n) für Liste
Zeilen 11-13: “Durschschneiden”
O(n) für Liste (zum Element laufen, durchschneiden)
O(n) für Array (Kopieren)
⇒ log n rekursive Aufrufe
⇒ jeder Aufruf hat O(n)
⇒ O(n log n)
Verbesserung: Suchraum durch zwei zusätzliche Variablen low , high einschränken.
6
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Object binarySearch(DataStructure d, int k, int l, int h)
// Annahme: Beim ersten Aufruf l=0, h=d.size()-1
if ((h-l) == 1)
return (d.get(0).key == k ? d.get(0) : null);
if ((h-l) == 0)
return null;
int probeIndex = l + (h-l+1) / 2;
Object probe = d.get(probeIndex);
if (probe.key == k)
return probe;
else
return (probe.key > k ?
binarySearch(d, k, l, probeIndex - 1) :
binarySearch(d, k, probeIndex + 1, h);
Laufzeitanalyse:
Zeilen 1-3,5-7: O(1)
Zeile 4:
O(1) für Array
O(n) für Liste
Zeile 8:
O(1)
⇒ Gesamtlaufzeit: O(n log n) für Liste, O(log n) für Array
Alternative: Laufzeitals
Rekursion
n
, T (1) = T (0) = c2
T (n) =
c1
+T
|{z}
| {z2 }
≈Zeilen 1-7
Zeile 8
Geratene geschlossene Form:
T (n) = c1 · log n + c2
Induktionsbeweis:
zu zeigen: T (n) = c1 + T ( n2 ) mit T (1) = c2 ⇔T (n) = c1 · log n + c2
√
Induktionsanfang: T (1) = c2 = c1 · 0 + c2
Induktionsannahme: Sei T (k) = c1 · log k + c2 ∀k ≤ n, k, n ∈ N
Induktionsschritt: Sei n0 = 2k für irgendein k ≤ n.
T (n0 )
n0
)
Rekursionsgleichung
2
= c1 + T (k)
= c1 + c1 · log k + c2
Induktionsannahme
= c1 + T (
= c1 (log(2k)) + c2
= c1 · log n + c2
7
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Laufzeit: average case
Im Allgemeinen: In Schritt i können genau 2i−1 Elemente gefunden werden.
Annahme: n = 2p − 1, p ∈ N
p
p
p
P
P
P
1
1
i · 2i = 2n
i · 2i
Tbin.Such,avg (n) = n1 i · 2i−1 = 2n
i=1
i=1
i=0
p
P
1
Sp := 2n
i · 2i
i=0
p+1
Sp + (p + 1) · 2
=
p
P
i+1
(i + 1) · 2
i=0
=
p
X
i+1
i·2
i=0
|
+
p
X
2i+1
i=0
{z
2·Sp
}
| {z }
2p+2 −2
⇒ Sp = 2p+1 (p − 1) + 2
Zurück zu T :
Tbin.Such,avg (n)
=
≈
=
1
(p − 1) · 2p+1 + 2
2n
1
(n · log n − n)
n
log n − 1
n = 2p − 1, p ≈ log n
Im Durchschnitt nur einen Aufruf weniger als im schlechtesten Fall.
4.3
Interpolationssuche
Motivation: Sie suchen “Laubfrosch” und schlagen den Duden bei “Paradoxon” auf Seite 800 auf.
L = 12 . . . Buchstabe
P = 16 . . . Buchstabe
Sie suchen weiter auf Seite 12
16 · 800 = 600
Allgemein: jLineare Interpolationssuche
k
· (k − l + 1) + l
probeIndex = k−d.get(l).key
∆
k . . . gesuchter Schlüssel
l . . . ”lower bound”
h . . . “higher bound”
∆ . . . noch “offener” Suchraum der Schlüssel
∆ : g.get(h).key − d.get(l).key
Beispiel:
j
70−50
150−50
k
· (22 − 3 + 1) + 3 = 8
Laufzeitanalyse unter der Annahme der Gleichverteilung: Wir zeigen, dass TInterpol’,avg =
O(log log n).
Interpol’: Leichte Variante der Interpolationssuche.
Idee: Suche Objekt an der Stelle probeIndex.
8
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Suche sukzessive an
probeIndex + i ·
probeIndex − i ·
√
√
n
,
wenn k größer und
n
,
wenn k kleiner
Frage: Wie oft müssen wir i inkrementieren (dekrementieren) bis der Suchraum
auf
√
⇒ Mindestens zwei Vergleiche an Stelle probeIndex, probeIndex + n.
√
neingegrenzt ist.
Wie hoch ist der Erwartungswert für die Anzahl C von nötigen Vergleichen?
C
=
X
i · P r [genau i Vergleiche nötig]
i≥1
=
X
P r [mindestens i Vergleiche nötig]
i≥1
Würfel:
1
1
1
1
1
1
6 · 1 + 6 · 2 + 6 · 3 + 6 · 4 + 6 · 5 + 6 · 6 = 3, 5
5
4
3
2
1
1 + 6 + 6 + 6 + 6 + 6 . . . Wahrscheinlichkeit, dass mindestens eines 1 gewürfelt wird.
Wann sind mehr als 2 Vergleiche nötig?
√
Wenn die tatsächliche Position x von k von der erwarteten Position µ := probeIndex um mehr als n
abweicht.
Wo liegt µ? Gleichverteilung
⇒ Jeder Schlüssel innerhalb von ∆ hat dieselbe Wahrscheinlichkeit p = k−d.get(l).key
, dass er kleiner ist
∆
als k.
Damit
die Wahrscheinlichkeit, dass von h − l + 1 = n Elementen, die wir aus ∆ ziehen, genau j kleiner
ist n
sind,
pj (1 − p)n−j .
j
Somit
n
X
n
µ =
j
pj (1 − p)n−j = pn
j
j=1
σ
2
= p(1 − p)n
Die Wahrscheinlichkeit, dass der Wert einer Zufallsvariablen um mehr als t von µ abweicht:
σ2
Chebyshev
t2
√
p(1 − p)n
t := (j − 2) · n
≤
(j − 2)2 n
√
in unserem Fall:
P r [|x − pn|] ≥ (j − 2) · n
P r [|x − µ| ≥ t] ≤
P1 1 Wegen p(1 − p) ≤ 14 ⇒ C ≤ 2 +
4 (i−2)2 = 2, 4
i≥3
√
T (n) = C + T ( n)
T (1) = O(1)
T (n) ≤ 2, 4 log log n
9
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
Rekursionen
Beispiel:
T (n)
i-ter Schritt
nach x Schritten
√ n +c
q √
n +c+c
= T
1
= T n 2 + 2c
= T
..
. 1
= T n 2i + i · c
1 = T n 2i+1 + (i + 1) · c
..
.
= T (2) +x · c
| {z }
=O(1)
1
n 2x
1
⇔ log n 2x
log n
T (n)
=
T (n)
=
=
2
1
=
· logn = 1
2x
= 2x ⇒ log log n = x
(x + 1) · c = 2, 4 log log n
9
n +n
5·T
10
= O(nk )
k konst.
Master-Theorem
Löse T (n) = a · T
n
b
+ f (n) mit a, b ≥ 1 und f (n) > 0.
Satz: Sei a ≥ 1, b > 1 konstant und f (n), T (n) nicht negativ mit T (n) = a · T
bzw. nb steht).
n
b
+ f (n) (wobei
n
b
für
n
b
1. Für f (n) = O n(logb a)− , > 0 ist T (n) = Θ nlogb a .
2. Für f (n) = Θ nlogb a ist T (n) = Θ nlogb a · logb n .
3. Für f (n) = Ω nlogb a+ , > 0 und a · f nb ≤ c · f (n) für c < 1 ⇒ T (n) = Θ(f (n)).
Beispiele:
• T (n) = 9 · T n3 + n
a = 9, b = 3
f (n) = nlog3 9−1 = n2−1 = n
⇒ Fall 1: T (n) = O nlog3 9 = O n2
• T (n) = T n2 + 1 (binäre Suche)
a = 1, b = 2
f (n) = 1 = nlog2 1 = n0 = 1
⇒ Fall 2: T (n) = O (1 · log2 n) = O(log n)
10
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
4
SUCHEN
• T (n) = 2 · T n2 + n log n (“divide and conquer”)
a=2=b
f (n) = nlog2 2− ? Gehtnicht! Satz nicht anwendbar.
Fall 3 fordert Ω n1+ , was durch n log n nicht erfüllt ist.
Beweis: Annahme: n = bi , i ∈ N
Teilprobleme haben Größe 1, b, b2 , . . . , bi
Lemma: Sei a > 1, b > 1, f (n) nicht negativ, n = bi
(
O(1)
für n = 1
T (n) =
a · T nb + f (n) für n = b
dann gilt:


logb n−1
T (n) = Θ nlogb a +
X
j=0
aj · f
n
bj

Beweis:
T (n)
n
= f (n) + a · T
nb n = f (n) + a f
+a·T 2
b n nb 2
+a ·T 2
= f (n) + a · f
b
n
n
bn 2
= f (n) + a · f
+ a · f 2 + a3 · T 3
b
b
b
..
.
logj n−1
n
X
=
aj · f j + Θ nlogb a
b
j=0
= alogb a · O(1) +
logP
b n−1
= nlogb a · O(1) +
logP
b n−1
aj · f
n
bj
j=0
aj · f
n
bj
j=0
Lemma: Sei a ≥ 1, b > 1, f (n) definiert auf bi , i ≥ 0. Sei g(n) definiert als g(n) =
logP
b n−1
j=0
aj · f
n
bj
.
1. Ist f (n) = O n(logb a)− , so ist g(n) = O nlogb a
Beweis:
11
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
Mit f (n) = \logb a− ist f
n
bj
=
logb a−
\
b|

g(n)
4
.
logb a−
logb n−1
X
= O
SUCHEN
aj ·
n

= O nlogb a− ·

bj
j=0
logb n−1 X
j=0

logb n−1
X
= O nlogb a−
a · b
blogb a

j


j
(b ) 
j=0
=
=
≤
=
·logb n
−1
O n
b − 1
logb a− n − 1
O n
· b −1
logb a−
O n
· n
O nlogb a
logb a− b
a
2. Mit f (n) = Θ nlogb gilt g(n) = Θ nlogb a · logb n .
Beweis:
logb a
Mit f (n) = Θ nlogb a ist f bnj = Θ bnj
.


g(n)
=
Θ
X
aj ·
n logb a
j=0

bj

=
=
=
j
1
logb a
b
j=0


j
X
1 
Θ nlogb a ·
aj ·
a
j=0


logb n−1
X
Θ nlogb a ·
1
Θ nlogb a ·
X
aj ·


j=0
=
Θ n
logb a
· logb n
n
3. Ist a · f b ≤ c · f (n), c < 1, n > b, so ist g(n) = Θ (f (n)).
Beweis: P
Da g(n) =
aj · f bnj ist g(n) ≥ f (n).
j=0
Noch zu zeigen:
g(n) = O(f (n))
Wegen a · f nb ≤ c · f (n) für c < 1 gilt aj · f bnj ≤ cj · f (n)
logP
b a−1
P j
loga n−1
c · f (n) = f (n) ·
cj = f (n) · c c−1 −1 ≤ O(f (n))
⇒ g(n) ≤
j=0
j=0
Es gilt alogb n = nlogb a , denn nlogb a = blogb n·logb a = alogb n .
12
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
5
SORTIEREN
Sortieren
Eingabe: Menge O von Objekten, auf denen eine Ordnung definiert ist, so dass für je zwei Objekte
o1 , o2 ∈ O jeweils entweder
a) o1 < o2
b) o1 == o2
c) o1 > o2 gilt.
Ausgabe: Die selbe Menge sortiert, so dass für alle Objekte oi (:= oi steht an Position i) und oj mit
0 ≤ i < j < |O| gilt oi ≤ oj .
Im Folgenden gehen wir von zu sortierendem Array S mit natürlichen Zahlen aus.
5.1
Sortieren durch Einfügen
Idee: Zweites S 0 mit der gleichen Länge n := |S|. Suche in Runde i ≥ 0 die kleinste Zahl aus S, streiche
sie in S, füge sie an Position i in S 0 ein.
Streichen implementieren
• durch eine negative Zahl (falls Eingabe nur positiv)
• durch null-Objekt
• durch zusätzliches boolean Array
Finitheit
√
, Korrektheit
√
Laufzeitanalyse: n Runden mit jeweils O(n) Laufzeit,
n−1
P
n−i=
i=0
n·(n−1)
2
Schlechte Laufzeit, weil wir jedes Element aus S mit jedem anderen vergleichen.
Idee: Wähle sogenanntes Pivotelement p und bilde zwei Mengen
K = {x ∈ S \ p|x ≤ p}
G = {x ∈ S \ p|x > p}
Wenn K und G sortiert sind, können wir S wie folgt zusammensetzen:
S = K[0] . . . K[|K| − 1]pG[0] . . . G[|G| − 1]
Sei k := |K| und g := |G|
⇒ Position von p im sortierten Array ist S[k].
⇒ Verfahren rekursiv auf die Teilmengen K und G anwenden. Wir führen Variablen lef tIndex,
rightIndex ein, um zu sortierende Teilbereiche zu kennzeichnen.
Es ist klar, dass alle Elemente aus K kleiner sind als alle Elemente aus G, d.h. wir sparen k · g Vergleiche.
5.2
QuickSort
Grobe Idee:
Quicksort (int[] s, int leftIndex, int rightIndex)
if (leftIndex < rightIndex)
int indexOfPivotElement = partition(s, leftIndex, rightIndex);
Quicksort(s, leftIndex, indexOfPivotElement - 1);
Quicksort(s, indexOfPivotElement + 1, rightIndex);
13
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
Was leistet Funktion partition?
• Wählt ein Pivotelement p aus. Hier p := S[lef tIndex]
• Setzt alle Elemente kleiner oder gleich p in linke “Hälfte”, größere in rechte “Hälfte” und p auf die
Position dazwischen.
• Diese Position wird zurückgegeben.
Idee: Wir benutzen zwei Zeiger
i := lef tIndex + 1
j := rightIndex
Das Verfahren teilt das Problem in Teilprobleme, “bezwingt” diese durch rekursive Anwendung und kombiniert diese Teillösungen dann zur Gesamtlösung.
⇒ Divide and Conquer Verfahren
Analyse: Allgemeine Rekursionsformel: T (n) = Θ(n) + T (|K|) + T (|G|) + O(1)
| {z }
| {z } |
{z
}
Divide
Conquer
Combine
Worst-case Analyse: Pivotelement ist Minimum bzw. Maximum
⇒ entweder |K| = 0 oder |G| = 0
⇒ T (n) = Θ(n) + T (n − 1) + O(1)
⇒ O(n2 )
⇒ genauso schlecht wie Sortieren durch Einfügen
Average-case Analyse: Annahme: Elemente sind paarweise verschieden. In jedem Teilproblem wählen wir zufällig ein Element aus allen als Pivotelement.
⇒ Die Wahrscheinlichkeit, das Element zu ziehen, das in der sortierten Folge an Position j steht, ist n1
für alle Elemente des Teilproblems.
Sei QS(n) die erwartete Anzahl von Vergleichen im Feld der Größe n.
Klar:
QS(0) = QS(1) = 0
Für n ≥ 2: QS(n) = |{z}
n +E(QS(j − 1) + QS(n − j))
Divide
Wenn das j-te Element der sortierten Folge als Pivotelement gewählt wird.
Wegen Linearität des Erwartungswertes:
n
n−1
P
P
QS(n) = n + n1 ·
(QS(j − 1) + QS(n − j)) = n + n2
QS(j)
j=1
j=1
14
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
Trick:
n · QS(n) = n2 + 2 ·
5
n−1
X
SORTIEREN
(1)
QS(j)
j=0
(n + 1) · QS(n + 1) = (n + 1)2 + 2 ·
n
X
(2)
QS(j)
j=0
2-1:
(n + 1) · QS(n + 1) − n · QS(n) = (n + 1)2 − n2 + 2 · QS(n)
⇔ (n + 1) · QS(n + 1) = n2 + 2n + 1 − n2 + QS(n) · (2 + n)
n+2
⇒ QS(n + 1) ≤ 2 +
· QS(n)
n+1
n+1
n+2
(2 +
· QS(n − 1))
⇒
2+
n+1
n
2
2
2
= 2 + (n + 2) ·
+ +
+ ...
n+1 n n−1
1
1
1
+ +
+ ...
= 2 + 2 · (n + 2) ·
n+1 n n−1
|
{z
}
harmonische Reihe
n+1
X1
= 2 + 2 · (n + 2) ·
i
i=1
≤ 2 + 2 · (n + 2) · (ln n + 1)
= O(n log n)
Anmerkung: Annahme kann erzwungen werden durch
• Shuffling
• Wählen des Pivotelements “uniformly at random”
5.3
Idee:
MergeSort
Teile zu sortierende Menge in zwei gleichgroße Hälften und sortiere diese (Divide & Conquer).
Kombiniere:
n
Allgemeine Rekursion: T (n) = O(n) + 2 · T ( ) + Θ(n)
| {z } | {z 2 }
| {z }
Divide
Conquer
Combine
Rückwärts-Analyse
MergeSort hat die Laufzeit O(n log n)
15
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
Variante: m-Wege-Mischen
Füge immer m sortierte Teilmengen zusammen.
⇒ Θ(n logm n)
5.4
Heap:
HeapSort
Ist ein binärer Baum mit Wurzel r. Formal ist ein Baum ein Graph, als solcher ist er ein Paar
T = (V, E)
V . . . Menge der Knoten
E ⊆ V × V . . . Menge der Kanten (Relation)
Kanten e = (v, w) sind gerichtet. v ist Vater von w. w ist Kind von v.
Was ist ein Baum?
Ein zykelfreier Graph. (Hierfür betrachten wir Kanten als ungerichtet.)
Ein Zykel ist ein Pfad, der mindestens einen Knoten mehrfach durchläuft.
Ein Pfad ist eine Folge von Kanten P (v, w) = {(v, v1 ), . . . , (vk−1 , w)}, so dass (v, vi ) ∈ E, (vk−1 , w) ∈ E und
∀ 1 ≤ i < k − 1 : (vi , vi+1 ) ∈ E.
Binärer Baum:
• Jeder Knoten außer der Wurzel hat einen Vater
• Jeder Vater hat höchstens zwei Kinder
Idee beim HeapSort: Sei S eine Menge zu sortierender Zahlen. Die Knoten speichern die Zahlen.
Baue Heap so auf, dass für alle Knoten gilt, dass die Kinder kleinere Werte haben.
⇒ Heapeigenschaft
Wenn die Teilbäume gleich groß sind, muss man nur log n Vergleiche machen, bis man den richtigen Vater
gefunden hat.
Beispiel: HeapSort
16
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
• Sortieren durch Minimum-Suche
• Minimum steht in Wurzel ⇒ Streichen und Heap neu aufbauen (2)
• Füge letztes Element im Baum an Stelle der Wurzel ein (3)
• Stelle Heapeigenschaft wieder her:
• Lasse 9 im Baum runtersinken (4)
• Falls 9 ≥ min(key(lchild), key(rchild)), tausche 9 mit min(lsohn, rsohn) per Iteration (5)
⇒ Heapeigenschaft erhalten
√
• Iteration mit Minimumsuche!
Korrektheit:
1. Im Heap steht in jeder Interation das minimale Element oben. Dieses wird jeweils herausgeschrieben.
2. Durch Runtersinkenlassen wird Heapeigenschaft wiederhergestellt.
Laufzeit: O(n · T (Wiederherstellen der Heapeigenschaft))
Ziel: O(log n) für Wiederherstellen der Heapeigenschaft
1. Vergleiche des Schlüssels mit Schlüssel der Kinder und anschließender Tausch möglichst in O(1).
2. Schätze die Zahl der Iterationen beim Runtersinken mit dem Ziel O(log n).
Benutze ausgewogene Bäume: Es gibt k ≥ 0, so dass alle Blätter die Tiefe k oder k + 1 haben und
Blätter auf Stufe k + 1 sitzen “ganz links”.
Ausgewogene Bäume haben eine kurze und einfache Darstellung als Array mit folgenden Eigenschaften:
Für Knoten mit Index i hat parent(v) den Index 2i , lchild(v) den Index 2i und rchild(v) den Index 2i + 1.
Tiefe: log n
17
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
Baum existiert nur implizit und wird explizit als Array dargestellt: 1. geht in O(1) und 2.?
Es fehlt: Initialisierung des Arrays: for all x ∈ S do Insert(x, h)
Insert(x, h)
Sei n die Größe von h
n←n+1
A(n)←x
finish ← (i=1)
while not
finish do
j← 2j
if A(j)<A(i) then
tausche(A(i), A(j))
i←j
else
finish←true
od
Laufzeit:
• Initialisierung: O(n · Höhe(h))
• n · T (Minimale Suche und Wiederherstellung) = O(n · Höhe(h))
Lemma: Hat ein ausgewogener Baum die Höhe k, so hat er mindestens 2k Knoten.
Beweis: per Induktion über k
⇒ Ein ausgewogener Baum mit n Knoten hat eine Höhe kleiner als log n.
Satz: HeapSort geht in O(n log n)
5.5
BucketSort
Gegeben seien Wörter über einem Alphabet Σ und |Σ| = m.
Sortiere lexikographisch:
Ordnung: a < b, a < aa < ab
Fall 1: Wörter haben alle Länge 1.
Wir stellen m Fächer zur Verfügung (für a, b, c, ..., z) und werfen die Wörter in die entsprechenden Fächer.
Anschließend werden die Fächer konkateniert.
Sei n = #Wörter, k die Länge (k = 1), dann ist die Laufzeit O(n + m).
Implementierung: Einzelne Fächer als lineare Listen und diese zusammen als Array.
18
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
Fall 2: Alle Wörter haben Länge k.
Sei ein Wort ai = ai1 ai2 . . . aik .
Idee:
Sortiere zuerst nach dem letzten Zeichen, dann nach dem vorletzten usw. Damit sind Elemente, die zum Schluss ins gleiche Fach fallen, automatisch geordnet.
⇒ O((n + m)k)
Beispiel: 124, 223, 324, 321, 123
k=3
Fächer:
1
1
3211
2
3
1231
1242
2
3211
2232
1233
1244
3245
2233
3
2232
1233
4
1244
3245
3214
3245
[Indizes zeigen die Reihenfolge des Aufsammelns.]
Problem: Aufsammeln der Listen.
⇒ Überspringe leere Listen mit dem Ziel, eine Laufzeit von O(nk + m) statt O(nk + mk) zu erreichen.
Trick: Erzeuge Paare (j, xij ) mit 1 ≤ i ≤ n und 1 ≤ j ≤ k. Sortiere nach der zweiten Komponente
und dann nach der ersten. Dann liegen im j-ten Fach die Zeichen sortiert vor, die an der j-ten Stelle
vorkommen.
Beispiel: Bilde (j, xj ) mit 1 ≤ j ≤ 3
j = 3: (3, 1), (3, 3), (3, 3), (3, 4), (3, 4)
j = 2 : (2, 2), (2, 2), (2, 2), (2, 2), (2, 2)
1
1
1
2
3
3
2
2
2
2
2
2
3
← 1. Komponente
1
← springe zu Fach 3
3
3
← springe zu Fach 4
4
4
↑
2. Komponente
Dadurch wird Durchlaufen leerer Fächer vermieden.
Nach dem Preprocessing sortiere wie oben mit dem Wissen, welche Fächer in der j-ten Iteration (1 ≤ j ≤
k) leer bzw. nicht leer sind.
⇒ O(nk + m) (Jedes Element wird k-mal angeschaut)
Fall 3: Wir nehmen an ai hat Länge li und L =
n
P
li mit dem Ziel O(L + m)
i=1
Idee:
Sortiere Wörter der Länge nach. Beziehe zuerst die langen Wörter in den Algorithmus ein.
1. Erzeuge Paare (li , ai ).
19
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
5
SORTIEREN
2. Sortiere Paare durch BucketSort nach ihrer ersten Komponente.
Sei L(k) die Liste der Wörter der Länge k.
3. Erzeuge L Paare (j, xij ) mit 1 ≤ i ≤ n und 1 ≤ j ≤ li .
Sortiere zuerst nach der zweiten Komponente und dann nach der ersten. Damit erhalten wir lineare
Listen, die nicht lineare Fächer angeben für die Iterationen 1 ≤ j ≤ lmax .
4. Sortiere ai durch BucketSort wie im Fall 2. Betrachte nur L(k)-Listen.
Satz: BucketSort sortiert n Wörter der Gesamtlänge L über dem Alphabet Σ mit |Σ| = m mit der Laufzeit O(L + m).
5.6
Auswahlproblem
Finde Median.
Gegeben ist eine Menge S von Zahlen und eine Zahl 1 ≤ i ≤ n. Finde ein x ∈ S mit |{y|y > x}| = i.
1. Idee:
Sortiere und laufe dann die Menge ab bis zur i-ten Stelle. → O(n log n)
2. Idee:
Ähnlich wie QuickSort. Bei perfekter Teilung erhält man n +
Also läuft es im Mittel in linearer Zeit, wenn p zufällig ist.
n
2
+
n
4
+
n
8
+ · · · ≤ 2n
Deterministisch: |S| = n
1. Wir teilen n Elemente in 5-er Gruppen auf, erhalten also
Gruppe.
n
5
Gruppen. Bestimme den Median in jeder
2. Suche rekursiv den Median x der Mediane.
3. Teile die Menge S bezüglich x in Mengen S1 , S2 auf. Sei |S1 ∪ x| = k, |S2 | = n − k.
4. Algorithmus:
if i=k then return x
else if i<k then Auswahl(S1 , i)
else Auswahl(S2 , i-k)
Wieso betrachten wir Mediane?
1
10 n
1
der Mediane sind größer als x und 10
n der Mediane sind kleiner als x. Die betreffenden Gruppen
3
liefern mindestens 3 Elemente, die größer bzw. kleiner sind als x. Also hat S1 mindestens 10
n Element,
7
genauso S2 . Außerdem ist |S1 | ≤ 10 n, genauso |S2 |.
7
⇒ T (n) = T ( n5 ) + T ( 10
n) + O(n) für n ≥ d konstant
T (n) = O(1) für n ≤ d.
Behauptung: T (n) ≤ c · n für c konstant
n
7
+c· n+a·n
5
10
9
≤ c· n+a·n
10
c
≤ c·n
für a ≤
10
T (n) ≤ c ·
20
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
public Object search (int key, Tree tree)
Node currentEl = tree.getRoot();
boolean found = false;
int currentKey;
while (currentEl != null && !found) {
currentKey = currentEl.getObject().getKey();
if (currentKey == key)
found = true;
else
currentEl = currentKey > key ? currentEl.lchild() : currentEl.rchild();
}
if (currentEl == null)
return null;
return currentEl.getObject();
Satz: In Zeit O(n) können wir deterministisch das i-t größte Element aus einer Menge der Größe n
finden.
Bemerkung: Wieso 5-er Gruppen und keine 3-er Gruppen, 7-er Gruppen, ...?
Wahl von a? Wahl von c?
c = 10 · a, a · n = n5 · Median(5 Elemente)
Für 5 Elemente braucht man zur Berechnung des Medians 4 + 3 + 2 = 9 Vergleiche.
6
Balancierte Bäume
Mit einem Heap kann man das minimale Element schnell finden und alle anderen Elemente in O(n). Wie
kann man binäre Bäume so aufbauen, dass man alle Element in O(n log n) finden kann?
6.1
Bäume
Bäume bestehen aus Knoten v, die auf andere Knoten zeigen können. In binären Bäumen zeigt jeder
Knoten auf höchstens zwei andere Knoten, seine sogenannten Kinder. Wir untersuchen lchild (linkes
Kind) und rchild (rechtes Kind). Der linke Teilbaum von v sind alle Knoten, die über v.lchild erreicht
werden können. Dies gilt für den rechten Teilbaum analog. Knoten speichern Objekte, die eindeutig mit
einer Zahl n ∈ N als Schlüssel assoziiert sind. Man unterscheidet zwei Arten der Speicherung.
Knotenorientiert: Ein Objekt pro Knoten. Für alle v gilt, dass der Schlüssel im linken Teilbaum kleiner ist als der Schlüssel des Objekts v, der wiederum kleiner ist als der Schlüssel von allen Objekten im
rechten Teilbaum.
Blattorientiert: Ein Objekt pro Blatt. Ein Schlüssel pro Nicht-Blatt (“innerer Knoten”). Für alle v gilt,
dass der Schlüssel von Objekten im linken Teilbaum von v kleiner ist als der Schlüssel von v und wieder
wiederum kleiner ist als die Schlüssel aller Objekte im rechten Teilbaum von v.
Hier: Knotenorientierte Speicherung. Wie können Suche und Einfügen implementiert werden?
Einfügen: Zuerst rufen wir Suche(v) auf und lassen uns den letzten besuchten Knoten zurückgeben.
Der zuletzt besuchte Knoten hat nur ein Kind. ⇒ Füge Objekt als neues Kind ein.
21
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Streiche(x) : Zuerst führen wir Suche(x) aus. Ist x ∈ T , endet die Suche in Knoten u mit dem zugehörigen Schlüssel x.
Fall 1:
u ist ein Blatt ⇒ streiche u
Fall 2:
u hat nur ein Kind w ⇒ streiche u und setze w an die Stelle von u als Kind im Elternknoten
v von u
Fall 3:
u hat zwei Kinder ⇒ suche den Knoten v mit dem größten Schlüssel im linken Teilbaum
(einmal links, dann rechts, bis es nicht mehr geht ⇒ v) ⇒ v hat höchstens ein Kind. Tausche
die Objekte von u und v. Lösche dann Knoten mit Fall 1 oder 2.
Komplexität der Operationen: O(h), wobei h die Höhe des Baumes ist (entspricht also dem längsten
Pfad von der Wurzel zu einem Blatt).
Problem: Höhe kann O(n) sein.
Idee:
1. Baue Baum von Zeit zu Zeit wieder ausgewogen auf
2. Balancierte Bäume
6.2
AVL-Bäume
Definition: Sei u ein Knoten in einem binären Baum. Balance(u) von u bezeichnet die Differenz der
Höhen von rechtem und linkem Teilbaum.
Definition: Ein binärer Baum heißt AV L-Baum, falls für alle Knoten v ∈ V |Balance(v)| ≤ 1 gilt. Wir
wollen nun zeigen, dass die Höhe in einem solchen Baum O(n log n) ist. Dazu definieren wir F IBONACCIBäume rekursiv wie folgt:
F IBONACCI-Zahlen sind ebenfalls rekursiv definiert: F0 = 0, F1 = 1, Fn = Fn−1 + Fn−2 ∀n ≥ 2
Folgerung: Tn enthält Fn Blätter.
Behauptung: AVL-Baum der Höhe h enthält mindestens Fn Blätter.
√
n=0
n = 1:
n ≥ 2: Man erhält blattärmsten AVL-Baum, wenn m an jeweils den blattärmsten AVL-Baum der Höhe
h − 1 mit dem blattärmsten AVL-Baum der Höhe h − 2 kombiniert.
Nach Induktionsannahme hat dieser Baum mindestens Fn−1 + Fn−2 = Fn Blätter.
22
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Bekannt: Für h ≥ 0 gilt
Fh
=
α
=
β
=
αh − β h
√
5
√
1+ 5
≈ 1, 6
2√
1− 5
≈ −0, 6
2
Lemma: Ein AVL-Baum mit n Knoten hat die Höhe O(log n).
Beweis: Der Baum hat höchstens n Blätter.
n ≥ Blätter ≥ Fn
Wenn h groß genug gewählt wird, erhält man:
Fh
n
⇒h
⇒h
αh
√
2 5
αh
√
≥
2 5
√
log(2 5 · n)
=
α
∈ O(log n)
≥
Wie geht jetzt das Einfügen und Streichen?
Zusätzlich assoziiert zu Knoten ist seine Balance.
Einfügen: Durch das Einfügen eines Knotens w können die Balancen einiger Vorfahren die Werte ±2
annehmen.
Sei u der tiefste dieser Vorfahren und sei ohne Beschränkung der Allgemeinheit Balance(u) = 2, so wurde
w im rechten Teilbaum eingefügt. Sei nun v das rechte Kind von u, dann muss sich die Höhe zusätzlich
erhöht haben, also ist die Balance von v = ±1.
Beachte:
1. Rotation bewahrt die Suchbaumeigenschaft.
2. u und v haben nach der Rotation eine Balance von 0
3. Alle Knoten in A, B und C behalten ihre (legale) Balance
4. Die Höhe von v ist nach der Rotation gleich der Höhe von u vor dem Einfügen von w. Also sind nach
der Rotation alle Vorfahren von w balanciert.
23
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Zusammenfasssung: Balance(u) = H(rT B(v)) − H(lT B(v)), wobei H(t) die Höhe des Baums t ist und
rT B(t) bzw. lT B(t) rechter bzw. linker Teilbaum von t sind.
AVL- Bäume haben für jeden Knoten v eine Balance(v) ≤ 1.
Problem: Balance kann beim Einfügen und Streichen verloren gehen.
Es gibt 4 Rotationsoperationen:
Sei u der tiefste Knoten mit Imbalance.
• Balance(u) = 2, Balance(v) = 1 ⇒ Rotation.links(u)
• Balance(u) = −2, Balance(v) = −1 ⇒ Rotation.rechts(u)
• Balance(u) = 2, Balance(v) = −1 ⇒ Doppelrotation.rechtsLinks(u)
• Balance(u) = −2, Balance(v) = 1 ⇒ Doppelrotation.linksRechts(u)
Beachte: Diese Operationen können durch Umhängen von Zeigern in O(1) implementiert werden.
Streichen von Elementen: Streichen erstmal wie im einfachen Suchbaum. Imbalancen wie beim Einfügen von unten nach oben (tiefster Knoten zuerst auflösen).
Vorsicht: Für |Balance(u)| = 2 und |Balance(v)| = 1 hat der Teilbaum an v nach der (Doppel-)Rotation
eine geringere Höhe als vorher der von u. Daher muss die Suche nach Imbalancen nach oben fortgesetzt
werden.
Satz:
Balancierte Bäume wie AVL-Bäume erlauben Suchen, Einfügen und Streichen in O(log n) Zeit, wobei n
die Knotenanzahl ist.
6.3
B-Bäume
Für große Datenmengen, die nicht in den Hauptspeicher passen, sind AVL-Bäume ungeeignet. Hier kommen B-Bäume zum Zuge, die für Zugriff auf externen Speicher entworfen wurden.
24
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Definition: Ein B-Baum der Ordnung k ≥ 2 ist ein Suchbaum
• dessen Blätter alle dieselbe Tiefe haben
• dessen Wurzel mindestens zwei und höchstens 2k − 1 Kinder hat
• in dem jeder andere (innere) Knoten mindestens k Kinder und höchstens 2k − 1 Kinder hat
Lemma: Sei T ein B-Baum der Ordnung k mit Höhe h und n Blättern, dann gilt: 2k h−1 ≤ n ≤ (2k − 1)h
Merksatz für “Höhe/Tiefe”:
Wie hoch stehen Sie in Ihrer Firmenhierarchie? “Unter mir sind 4 Leute.”
Wie tief stehen Sie? “Über mir sind x Leute.”
Logarithmieren der Formel aus dem Lemma ergibt
log2k−1 n ≤ h ≤ 1 + logk
n
2
⇒ Höhe vom B-Baum liegt in O(log n)
Operationen: Zugriff (Suche), Einfügen, Streichen
Annahme: Wir speichern knotenorientiert.
Betrachte Knoten u mit k ≤ l ≤ 2k − 1 Kindern.
Die Schlüssel k1 bis kl sind sortiert. Sei Ti der i-te Teilbaum von u, dann gilt für alle Knoten v ∈ Ti und
alle Schlüssel s in v:
• s ≤ si , falls i = 1
• si−1 ≤ s ≤ si , falls 1 < i < l
• si−1 < s, falls i = l
Suche(a, S)
Starte in Wurzel w und suche den kleinsten Schlüssel si in w mit a ≤ si
Wenn a = si ⇒ Element gefunden
Falls si =null: Suche rekursiv weiter im rechtesten Kind
Sonst: Suche rekursiv weiter im Teilbaum Ti
25
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
)
Laufzeit: O(logk n ·
k
) kann verbessert werden zu O(logk n ·
log k
|{z}
| {z }
| {z }
binäre Suche
Höhe lineare Suche
Einfügen(a, S)
(Erfolglose) Suche endet in Blatt b mit Elternknoten v, der l Kinder hat.
<
si (falls existent). Füge neuen
Sei wieder si der kleinste Schlüssel mit a
Schlüssel (samt Objekt) vor si ein (oder ganz rechts) und füge neues Blatt b’
ein, auf das der Pointer nach a zeigt.
Falls l vor dem Einfügen < 2k − 1 ist: Alles okay.
Falls l=2k-1: Spalte v in zwei Knoten v’ und v” mit jeweils k Kindern. Vor der
Spaltung enthält v 2k-1 Schlüssel. Nimm den mittleren Schlüssel und füge ihn im
Vaterknoten an die richtige Stelle
Dadurch kann es rekursiv nach oben zu weiteren Aufsplittungen kommen.
Falls die Wurzel gesplittet werden muss, wird oberhalb von der alten Wurzel ein
neuer Knoten kreiert, der als einzigen Schlüssel den mittleren Schlüssel der
alten Wurzel bekommt und auf v’ und v” zeigt. (Daher gilt für die Wurzel, dass
sie mindestens zwei Kinder haben muss.)
Streichen eines Schlüssels aus einem B-Baum:
Annahme: a=sj kommt in Knoten u vor
Mittels Suche(a, S) suche zunächst Knoten u, in dem a als Schlüssel sj vorkommt.
Allgemeine Situation:
Fallunterscheidung:
1. Tj ist ein Blatt, dann lösche sj und Tj .
2. Tj ist kein Blatt. Sei s der größte Schlüssel in Tj , dann ersetze sj durch s und lösche s samt seinem
Blatt in Tj .
Sei v der Knoten in Tj mit dem größten Schlüssel und r die ursprüngliche Anzahl der Kinder von v mit
k ≤ r ≤ 2k − 1.
1. Falls r > k (bzw. r > 2, falls v die Wurzel ist), ist alles okay, denn die B-Baum-Eigenschaft bleibt
erhalten.
2. Sei r = k und v nicht die Wurzel:
Sei w der Elternknoten von v und v 0 das Kind links von v und s0 der Schlüssel in w zwischen diesen
beiden Kindern.
Verschmelze nun v 0 und v:
26
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Wegen k ≤ l ≤ 2k − 1 hat vneu jetzt mindestens k+k − 1 = 2k − 1 Kinder und höchstens 2k − 1 + k − 1 =
3k − 2 Kinder.
Falls vneu mehr als 2k − 1 Kinder hat, wird er wieder (wie
beim Einfügen auch) gesplittet. Jedes der
Kinder hat dann mindestens k Kinder und höchstens 3k
2 − 1 Kinder.
Anmerkung: Hat vneu genau 2k − 1 Kinder, darf nicht gespalten werden. Jedoch hat nun w ein Kind
verloren und so muss rekursiv nach oben fortgefahren werden.
Zusammenfassung: B-Bäume
Zugriff (Suchen), Einfügen und Streichen kann in B-Bäumen der Ordnung k, die n Schlüssel verwalten,
in Zeit O(k · log n) durchgeführt werden.
6.4
Kantenmarkierte Suchbäume (“Tries”)
Bisher haben wir Suchbäume so organisiert, dass der direkte Vergleich von Schlüsseln den weiteren
Suchpfad im Baum bestimmt. Für sehr lange Schlüssel über einem Alphabet Σ sind Vergleiche der Art
“1. Buchstabe von x <1. Buchstabe von y?” sinnvoller.
Idee: Jeder Knoten hat wieder mehrere Kinder, aber für jeden Buchstaben des Alphabets höchstens
einen.
Definition: Sei Σ ein festes, endliches Alphabet.
1. Ein Baum heißt Σ-markiert, falls gilt:
(a) Jede Kante (u, v) ∈ E ist mit einem Buchstaben a ∈ Σ markiert. v heißt dann a-Sohn von u.
(b) Jeder Knoten hat höchstens einen a-Sohn.
2. Sei T = (V, E) ein Σ-markierter Baum, dann ist φ : V → E ? definiert durch:
φ(v)
= (leeres Wort), wenn v Wurzel von T
φ(v)
= φ(u)a, wenn v der a-Sohn von u ist
Wir sagen: v definiert das Wort φ(v) ∈ Σ? . φ(v) ist das Wort, das entsteht, wenn man die Buchstaben
entlang des Pfades P (w, v) von der Wurzel w zum Knoten v konkateniert.
3. Sei S ⊆ Σ? , dann heißt T kantenmarkierter Suchbaum für S (engl. “Trie”) falls gilt:
(a) Für jedes Blatt v ∈ T ist φ(v) das Anfangswort (Präfix) eines Wortes x ∈ S.
(b) Zu jedem x ∈ S gibt es genau ein Blatt v, so dass φ(v) das Anfangswort von x ist.
Das Blatt v trägt als Information dasjenige Element x ∈ S, das mit φ(v) beginnt.
⇒ blattorientierte Speicherung
27
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Beachte: Einen Trie gibt es nur für solche Mengen S, die präfixfrei sind, d.h. kein x ∈ S ist ein echtes
Anfangswort eines y ∈ S.
Präfixfreiheit lässt sich stets erreichen, indem ein neuer Buchstabe zu Σ hinzugefügt wird, z.B. #. Dieser
Buchstabe markiert ab jetzt das Ende eines Wortes, so dass z.B. BAU # nicht mehr Präfix von BAU M #
ist.
Auf Σ sei eine Ordnung definiert, z.B. a < b < · · · < z (lexikalische Sortierung). Seien nun die Söhne jedes
Knotens nach dieser Ordnung sortiert, so sind in den Blättern die Elemente von S aufsteigend von links
nach rechts sortiert.
Nachteile von Tries:
• Tries sind oft sehr dünn besetzt, d.h. fast alle Knoten haben weniger als |Σ| Kinder.
Diese Kinder könnte man verwalten
1. als Array:
Vorteil:
Nachteil:
2. als Liste:
Vorteil:
Nachteil:
direkter Zugriff auf den nächsten Buchstaben per Index
P
Platzbedarf |Σ| · #Knoten statt nur v∈V Grad(v)
P
Platzbedarf v∈V Grad(v)
Nur lineare Suche beim Zugriff
• Es kann lange Wege im Baum geben ohne Verzweigungspunkte.
6.5
PATRICIA-Bäume
Idee:
1. Setze Σ = {0, 1} und betrachte Binärcodierung von Buchstaben und Wörtern.
2. Ziehe die Wege ohne Verzweigung zu einem Knoten zusammen. Kennzeichne diesen Knoten mit der
Anzahl der übersprungenen Buchstaben.
⇒ PATRICIA-Bäume (Practical Algorithms To Retrieve Information Coded In Alphanumerics)
• Patricia-Bäume sind geeignet für sehr lange Schlüssel unterschiedlicher Länge.
• Sie sind binäre Bäume, deren linker Sohn immer der 0-Sohn ist (rechts der 1-Sohn).
• Jeder innere Knoten hat ein Feld ’skip’, das angibt, wie lang der Weg ist, den dieser Knoten repräsentiert, d.h. wie viele Buchstaben überlesen werden müssen.
• In den Blättern stehen die Schlüssel.
Beispiel: Suche(THAT, P), P ... Patricia-Baum (vom Beiblatt).
THAT: 10111010000000110111
1 + 0 = 1. Buchstabe= 1 ⇒rechts
1 + 11 = 12. Buchstabe= 0 ⇒links
12 + 1 = 13. Buchstabe= 0 ⇒links
⇒ Steht im gefundenen Blatt und ist also im Baum enthalten.
Beispiel: Suche(USA, P), P ... Patricia-Baum (vom Beiblatt).
USA: 110001011000001
1 + 0 = 1. Buchstabe= 1 ⇒rechts
1 + 11 = 12. Buchstabe= 0 ⇒links
12 + 1 = 13. Buchstabe= 0 ⇒links
⇒ Steht nicht im Blatt und ist daher nicht im Baum vorhanden.
28
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6.6
6
BALANCIERTE BÄUME
Randomisierte Suchbäume: Skiplists (W. Pugh)
Idee von Skiplists ist, dass eine sortierte Liste mit zusätzlichen, in einer bestimmten Weise zufällig gewählten Verlinkungen die wesentlichen Operationen “Suchen”, “Einfügen” und “Löschen” in O(log n) unterstützt.
Gegeben:
• Eine sortierte Teilmenge S aus einem Universum U mit einer natürlichen Ordnung, d.h. S =
{x1 , x2 , . . . , xn } mit xi < xi+1 für alle 1 ≤ i < n.
• Eine Levelzuweisung L : S → N+
Die Levelzuweisung definiert Teilmengen, die Levelmengen Li , so dass x ∈ Li ⇔ L(x) ≥ i. Es gilt also
S = L1 ⊇ L2 ⊇ · · · ⊇ Lv ⊇ ∅, wobei Lv das höchste, nicht-leere Level repräsentiert.
Eine Skiplist wird nun wie folgend gebildet:
• Definiere einen Anfangsknoten, den “header”, der jeweils auf das kleinste Element jedes Level Li
zeigt.
• Für alle Li : Jedes Element in Li zeigt auf das nächstgrößere Element in Li .
• Diese Zeiger sind mit i markiert und pro Knoten absteigend sortiert.
• Jedes größte Element im Level Li zeigt auf “null”.
Wie kann die Levelzuweisung erfolgen?
Zufällige Levelzuweisung:
Wähle für die Skiplist 0 ≤ p ≤ 1. In dem Moment, in dem ein Element x eingefügt wird, zieh so lange eine
positive Zufallszahl ≤ 1 bis das Ergebnis ≥ p. Die Anzahl der Züge ist der Level l, der x zugewiesen wird.
public int randomLevel (double p)
int level = 1;
Random random = new Random(11265);
while random.nextDouble() < p
++level;
return level;
Die zurückgegebene Levelzuweisung folgt einer geometrischen Verteilung, d.h. dass die Wahrscheinlichkeit, dass level = k ist, ist:
P [level = k] = pk−1 (1 − p)
Und der Erwartungswert einer solchen Verteilung ist
E(level) =
∞
X
k · pk−1 · (1 − p) =
k=1
1
1−p
⇒ Erwarteter Platzverbrauch einer solcher Art zufälligen Skiplist ist O(n).
Wie hoch ist die höchste erwartete Levelzuweisung?
Lemma: Die Zahl der Level v bei zufälliger Levelzuweisung hat den Erwartungswert O(log n). Es gilt
sogar, dass v ∈ O(log n) mit hoher Wahrscheinlichkeit.
[“Mit hoher Wahrscheinlichkeit” bedeutet, dass das Gegenereignis höchstens Wahrscheinlichkeit
29
1
n
hat.]
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
6
BALANCIERTE BÄUME
Beweis: v = max {L(x)|x ∈ S}
1
. Die Wahrscheinlichkeit, dass L(x) größer als ein
L(x) ist geometrisch verteilt mit Erwartungswert 1−p
t
gewähltes t ∈ N ist, ist < p . Da die Levelzuweisung für alle Elemente unabhängig ist, ist die Wahrscheinlichkeit, dass es ein Element x (von n Elementen) gibt mit L(x) > t kleiner oder gleich n · pt ist (für p = 21
also 2nt ).
Wir setzen t = α · log n [α > 2].
n
1
1
1
⇒ P [v > α · log n] ≤ 2α·log
n = nα−1 < n für p = 2 .
⇒ Höhe der Skiplist mit hoher Wahrscheinlichkeit in O(log n) ist.
Suche(y, S)
Die Zeiger eines Knotens seien absteigend nummeriert mit der Nummer des Levels des Elements, auf das
der Zeiger zeigt. Starte im header mit levelpointer auf das maximale, nicht leere Level v. In dem aktuellen
Knoten überprüfen wir für die Zeiger kleiner oder gleich dem levelpointer in absteigender Reihenfolge, ob
der Wert des Elements, auf das sie zeigen, kleiner oder gleich y ist. Gibt es keinen solchen Zeiger, dann ist
y nicht in S enthalten. Ansonsten setze den levelpointer auf das Level des gefundenen Zeigers und folge
dem Zeiger auf das nächste Element. Setze die Suche dort rekursiv fort.
Laufzeit: Wir unterteilen die Suchstrecke in zwei Teile:
a . . . Wegstrecke zum maximalen Level Lv
b . . . Wegstrecke zu niedrigeren Leveln
wird gebunden durch die Anzahl der Elemente in Lv . Wir betrachten dazu die Anzahl von
Knoten in Level v 0 : v 0 = log p1 n
a
Ganz allgemein:
Die Wahrscheinlichkeit, dass ein Knoten x in Level k + 1 ist, ist < pk . Die Anzahl von Elementen in Level k ist erwartet ≤ n · pk = 1. Wir suchen k, so dass erwartet nur ein Element
in dem Level ist.
k
1
n=
⇔ log p1 n = k
p
Wir machen eine Rückwärtsanalyse, d.h. wir gehen von dem gefundenen Element zum höchsten Level. Sei also C(k) die erwarteten Kosten, um in einem Knoten mit Level ≥ k zu kommen, mit C(0) = 0, C(1) = 1. Um in einem Knoten mit Level k zu sein, waren wir vorher
(Rückwärtsanalyse!) entweder in einem anderen Knoten in dem gleichen Level oder in dem
gleichen Knoten auf Level k − 1.
b:
Da die Wahrscheinlichkeit, dass der zuletzt besuchte Knoten in Level k − 1 gleichzeitig auch
in Level k ist, ist p, dass er es nicht ist 1 − p.
C(1) = 1
C(k) = (1 − p)(1 + C(k)) + p (1 + C(k + 1))
C
A
B
D A
E
A . . . Kosten für Folgen von Zeiger
B . . . Wir waren schon in Level k
C . . . Wahrscheinlichkeit, dass wir in Level k bleiben
D . . . Wahrscheinlichkeit, dass wir ein Level aufsteigen
E . . . Kosten, um Level k − 1 zu erreichen
C(k) =
k
p
(Umformungen)
Da das maximale k in O(log n) liegt, ist auch b in O(log n) und damit der gesamte Suchpfad in O(log n).
30
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
Einfügen(y, S)
Bestimme das Level L(y) wir beschrieben. In jedem Level suche Einfügestelle, lege 2 · L(y) Zeiger neu an.
⇒ Laufzeit O(log n)
Streiche(y, S)
Führe zuerst Suche(y, S) aus. Lege in jedem der besuchten Level die Zeiger auf y auf den Nachfolger von
y. ⇒ Laufzeit O(log n)
Satz: In einer zufälligen Skiplist für die Menge S der Größe n können Suchen, Einfügen und Streichen
in erwarteter Zeit O(log n) implementiert werden.
Da keinerlei Rebalancierungen ausgeführt werden müssen, ist diese Datenstruktur sehr einfach.
7
Graphenalgorithmen
Bisher haben wir uns hauptsächlich mit ungerichteten Graphen beschäftigt. Wenn Kanten nicht eine
Menge von Knoten, sondern ein geordnetes Paar darstellen, dann nennen wir den Graph gerichtet.
Das Element e = (v, w) ∈ E heißt Kante von v nach w. v ist der Startknoten und w der Zielknoten. w ist
Nachbar(-knoten) von v bzw. w ist adjazent zu v.
Für einen Pfad P (v, w) in einem gerichteten Graphen muss die Kantenfolge aus Kanten mit der richtigen
Richtung bestehen, d.h. P (v, w) = (e1 , e2 , . . . , ek ), dann muss
e1 = (v, v1 )
ek = (vk−1 , w)
Für alle 1 < i < k ist ei = (vi−1 , vi )
Allgemein: Startknoten der (1 < i ≤ k)-ten Knte ist Zielknoten der (i − 1)-ten Kante.
Beispiel: Der Pfad (a, d) existiert. Nämlich P (a, d) = ((a, b), (b, c), (c, d)). Der Pfad P (d, a) existiert nicht.
Ein gerichteter Graph heißt zyklisch, wenn er mindestens einen gerichteten Zykel enthält und sonst
azyklisch (engl. DAG = directed acyclic graphs). Falls es einen gerichteten Pfad von v nach w in G gibt, so
?
schreibt man v → w.
G
Konventionsgemäß bzw. mathematisch korrekt:
• (v, w): gerichtete Kanten
• {v, w}: ungerichtete Kanten
31
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7.1
7
GRAPHENALGORITHMEN
Darstellung von Graphen
Sei G = (V, E) mit V = {0, 1, . . . , n}. Es gibt zwei Darstellungsarten für Graphen:
1. Darstellung als Adjazenzmatrix A = (aij ):
0 ≤ i, (
j<n
1 , falls e = (i, j) ∈ E
aij =
0 , sonst
Bei ungerichteten Graphen ist die Adjazenzmatrix symmetrisch. Der Platzbedarf für diese Darstellung beträgt O(n2 ). Das ist günstig, wenn die Anzahl der Kanten m ∈ O(n2 ).
Aber: Insbesondere in realen Netzwerken ist E “dünn”, d.h. die meisten Knoten haben nur sehr wenige Kanten zu anderen Knoten. ⇒ m ≈ O(n)
Insbesondere zwei Graphenklassen haben nur O(n) Kanten:
• Bäume: n − 1 Kanten
• Planare Graphen sind solche, die sich auf der Ebene zeichnen lassen, ohne dass sich Kanten
kreuzen. Nicht-planare, ungerichtete Graphen sind beispielsweise:
Vollständig
Vollständiger
bipartiter
Graph
Graph
5-Clique
Ein Graph heißt “bipartit”, wenn sich seine Knotenmenge V in zwei Teilmengen teilen lässt, so
dass es zwischen Knoten der selben Teilmenge keine Kanten gibt.
Mitteilung: Ein planarer Graph hat m ≤ 3n − 6 Kanten , also m ∈ O(n).
2. Darstellung als Adjazenzliste:
Speichere für jeden Knoten v seine Nachbarn in einer verketteten Liste. Wenn G gerichtet ist, hat
jeder Knoten zwei Listen:
• InAdj(v) = {w ∈ V |(w, v) ∈ E}
• OutAdj(v) = {w ∈ V |(v, w) ∈ E}
Wenn G ungerichtet ist:
• Adj(v) = {w ∈ V | {w, v} ∈ E}
Platzbedarf: O(n + m)
Nachteil: Zugriffszeit auf eine Kante ist abhängig von der Listenlänge, also dem Knotengrad.
Bei gerichteten Graphen unterscheiden wir zwei Knotengrade:
• Eingangsgrad indegree(v) = |InAdj|
• Ausgangsgrad outdegree(v) = indegree(v) = |OutAdj|
Ein gerichteter Graph ist ein gerichteter Baum, wenn gilt:
(a) ∃v0 ∈ V mit indegree(v0 ) = 0 und
(b) ∀v ∈ V \ {v0 } : indegree(v) = 1 und
(c) Graph muss azyklisch sein
32
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7.2
7
GRAPHENALGORITHMEN
Topologisches Sortieren
Sei G = (V, E) ein gerichteter Graph, dann heißt die Abbildung num : V → {1, 2, . . . , n} mit n = |V |
topologische Sortierung, falls für alle e ∈ E gilt: (e = (u, v)) : num(u) ≤ num(v)
Lemma: G besitzt genau dann eine topologische Sortierung, wenn er azyklisch ist.
Beweis:
“⇒”:
Angenommen G ist zyklisch, dann ist (v0 , v1 , . . . , vk = v0 ) ein Kreis. Es muss gelten: num(v0 ) <
num(v1 ) < · · · < num(vk ) = num(v0 ) Widerspruch!
“⇐”:
Sei G azyklisch.
Behauptung: G enthält einen Knoten v mit indeg(v) = 0 (# eingehender Kanten).
Beweis per Induktion:
• Anfang: |V | = 1: klar
• Schritt: |V | > 1 : Entferne beliebigen Knoten v ∈ V und erhalte einen Graph G0 = (V 0 , E 0 )
mit V 0 = V \ {v}, E 0 = E ∩ (V 0 × V 0 ).
Nach Annahme ist G0 azyklisch und enthält ein v 0 mit indeg(v 0 ) = 0.
Entferne v 0 aus G und erhalte G00 , der wieder ein v 00 enthält mit indeg(v 00 ) = 0. Lies den
Beweis nochmals mit v = v 00 .
Es gilt: Entweder ist indeg(v 0 ) = 0 in G oder indeg(v 00 ) = 0 in G, weil andernfalls:
(v 00 , v 0 ) ∈ E und
(v 0 , v 00 ) ∈ E
Das kann aber nicht sein, da G azyklisch ist.
topSort(G)
√
|V|=1:
|V|>1:
wähle v mit indeg(v)=0
entferne v und weiter rekursiv auf G’=(V’,E’)
sei num’: V’→{1,...,|V’|}
eine topologische Sortierung für G’
(
num0 (w) + 1 , falls w 6= v
Dann num(w)=
1
, falls w = v
33
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
count ← 0
while ∃v ∈ V mit indeg(v)=0 do
count++
num(v)←count
streiche v und alle ausgehenden Kanten
endwhile
if count < |V| then “G zyklisch”
Ziel: O(|{z}
n + |{z}
m ) ⇒ Adjazenzlisten!
|V |
|E|
Ausgehende Kanten löschen: O(outdeg(v))
P
Alle löschen: v outdeg(v) = O(n + m)
Benutze in-zähler-Array: beim Löschen
der Kante (v, w) dekremtentiere
inzaehler[w],
Merke alle Knoten mit inzaehler = 0 in
Menge ZERO (als Stack) ⇒ O(n + m)
7.3
Durchmusterungsalgorithmen
Bestimme alle Knoten, die von einem gegebenen s ∈ V erreichbar sind.
S ← {s}
Markiere alle Kanten als unbenutzt.
while ∃(v, w) ∈ E mit v ∈ S und (v,w) unbenutzt do
sei e=(v,w) eine solche Kante
markiere e als benutzt
S←S ∪ {w}
endwhile
Invariante: In S sind diejenigen Knoten, die über benutzte Kanten erreichbar sind.
Probleme:
1. Realisierung benutzt ↔ unbenutzt
2. Finde geeignete Kante
3. Realisierung von S
Lösung:
1. Halte für jede Adjazenzliste einen Trennzeiger p(v) zwischen benutzten und unbenutzten Kanten
aus V . Verschiebe ihn nach rechts.
v → w1 → w2 → w3 → w4 → w5
|
{z
} ↑ |
{z
}
benutzt p(v) unbenutzt
2. Wir halten S̃ ⊆ S.
In S̃ stehen Knoten, für die es noch unbenutzte ausgehende Kanten gibt.
34
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
3. “Initialisierung”, “Einfügen” und “Ist w ∈ S?” sind Operationen.
Implementiere S als Boolean-Array, ⇒ jeweils in O(1)
Operationen auf S̃: “Initialisierung”, “S̃ = ∅?”, “Einfügen”, “Wähle v ∈ S̃ beliebig und streiche es
eventuell”
Implementiere S̃ als Stack oder als Queue oder als Heap.
Allgemeiner Durchmusterungsalgorithmus
siehe Extrablatt
Durch Änderung von Zeile 9 (Addieren von w an letzter/erster Stelle) ändert sich das Durchmusterungsverhalten stark.
letzte Stelle: Breitensuche (Breadth First Search, BFS)
erste Stelle: Tiefensuche (Depth First Search, DFS)
7.3.1
Tiefensuche
Implementierung ist speicherplatzineffizient (wegen der Zeiger). Rekursive Form der Tiefensuche:
1
void DFS (Node v, boolean[] visited)
2
3
4
5
6
7
visited[v] = true;
for all (v, w) ∈ E do
if not visited[w]
DFS(w, visited);
endif
endfor
Überzeugen Sie sich von der Äquivalenz der Algorithmen.
Die Tiefensuche unterteilt die Kanten des Graphen in vier Klassen T , B, F , C je nach Art des Besuches.
Sei (v, w) die in Zeile 3 betrachtete Kante, dann
(A) gehört (v, w) zu den Baumkanten T (tree), wenn w vorher nicht nicht besucht wurde.
?
(B) gehört (v, w) zu den Vorwärtskanten F (forward), falls w schon besucht wurde und ∃v → w, d.h.
T
wenn es einen Pfad von v nach w in T gibt.
?
(C) gehört (v, w) zu den Rückwärtskanten B (backward), falls w schon besucht wurde und ∃w → v.
T
?
?
T
T
(D) gehört (v, w) zu den Querkanten C (cross), falls weder v → w, noch w → v existieren.
Wir erweitern den rekursiven Algorithmus um df snum[v] und compnum[v], wobei
df snum[v] angibt, als wievielter Knoten v zum ersten Mal besucht wurde.
compnum[v] angibt, als wievielter Knoten v’s DFS-Aufruf beendet war (completed).
35
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
for all v ∈ V do
visited[v] = false
Initialisiere dfsnum[v] und compnum[v] auf 0
endfor
Setze globale Zähler z1, z2 auf 0
Initialisiere leere Mengen T, B, C, F
for all v ∈ V do
if not visited[v] then
DFS(v)
endfor
Laufzeit: O(n + m), da
a) die Einzellaufzeit eines Aufrufs ohne Rekursion O(1 + outdegree(v)) ist.
P
b) für jeden Knoten nur einmal ein DSF-Aufruf gemacht wird: O( v∈V (1 + outdegree(v)) = O(n + m)
Lemma: Eigenschaften, Teil 1
a) Kantenklassen T , B, C, F bilden eine Partition der Kantenmenge E. (Beweis ist trivial.)
b) T entspricht dem Wald (Menge von Bäumen) der rekursiven Aufrufe. (Beweis ergibt sich einfach
aus dem Algorithmus.)
?
c) v → w ⇔ df sum[v] ≤ df snum[w] ∧ compnum[w] < compnum[v]
T
?
?
T
T
d) Seien v, w, z ∈ V mit v → w, (w, z) ∈ E und ¬(v → z), dann gilt:
(i) df snum[z] < df snum[v]
(ii) (w, z) ∈ B
(iii) compnum[z] > compnum[v] ⇔ (w, z) ∈ B
(iv) compnum[z] < compnum[v] ⇔ (w, z) ∈ C
Beweis:
?
c) v → w
T
⇔ Aufruf DF S(w) ist geschachtelt in DF S(v)
⇔ df num[v] ≤ df snum[w] ∧ compnum[w] ≤ compnum[v]
d) Schrittweise:
36
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
?
• aus v → w folgt, dass dsf num[v] ≤ df snum[w]
T
• aus (w, z) ∈ E folgt, dass DF S(v) aufgerufen wird, bevor DF S(w) und DF S(v) enden.
?
• ¬(v → w) ⇔ DF S(z) nicht in DF S(v) geschachtelt ist (folgt aus c).
T
⇒ DF S(z) startet vir dem Aufruf DF S(v)
⇒ df snum[z] < df snum[v] (i bewiesen)
• Wegen df num[z] < df snum[w] folgt, dass (w, z) ∈
/ T und wegen (w, z) ∈
/ T ∧ df snum[z] <
df snum[v] < df snum[w] folgt, dass (w, z) ∈
/ F ⇒ (w, z) ∈ B ∪ C (wegen a). (Beweis für ii)
Def ?
?
?
?
• (w, z) ∈ B ⇔ z → w ⇔ z → v [da v → w existiert und wir wissen, dass ¬(v → z) ist, muss das
T
T
T
T
die einzige Möglichkeit sein) ⇒ compnum[z] > compnum[v] (Beweis zu iii)
Def
?
?
• (w, z) ∈ C ⇔ weder w → z noch z → w
T
T
Wir wissen, dass df snum[z] < df snum[w]. Wegen c folgt nun, dass compnum[z] < compnum[w] <
?
compnum[v] (denn sonst gäbe es z → w) (Beweis zu iv).
T
Lemma: Eigenschaften, Teil 2 Sei (v, w) ∈ E
e) (v, w) ∈ T ∪ F ⇔ df snum[v] < df snum[w]
f) (v, w) ∈ B ⇔ df snum[w] < df snum[v] ∧ compnum[w] > compnum[v]
g) (v, w) ∈ C ⇔ df snum[w] < df snum[v] ∧ compnum[w] < compnum[v]
Beweis:
?
e) (v, w) ∈ T ∪ F ⇒ v → w ⇒ df snum[v] ≤ df snum[w]
T
Sei nun df snum[v] ≤ df snum[w]. Da (v, w) ∈ E, muss DF S(w) vor Abschluss von DF S(v) aufgerufen
werden.
⇒ echte Schachtelung der Aufrufe
?
⇒v→w
T
⇒ (v, w) ∈ T ∪ F
37
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
Bemerkungen:
1. Ob eine Kante e = (v, w) in T , B, C, F liegt, kann also (Lemma) durch Vergleich der df snum und
compnum festgestellt werden.
2. In azyklischen Graphen gibt es keine Rückwärtskanten, d.h. ∀(v, w) ∈ E compnum[v] > compnum[w].
⇒ Nummerierung num(v) = n + 1 − compnum[v]ergibt eine topologische Sortierung.
7.3.2
Starke Zusammenhangskomponenten (SZKs)
Definition: Ein gerichteter Graph G = (V, E) heißt stark zusammenhängend genau dann, wenn ∀v, w ∈
?
?
V gilt: v → w und w → v.
E
E
Die maximal stark zusammenhängenden Teilgraphen von G heißen starke Zusammenhangskomponenten
(Maximal: Es kann keine Kante hinzugefügt werden ohne dass diese Bedingung verletzt wird.)
Idee für Algorithmus: Erweitere DFS
Sei G0 = (V 0 , E 0 ) der bisher erforschte Teil von G. Verwalte die starken Zusammenhangskomponenten
von G:
Starte V 0 = {S}, E 0 = ∅, SZK = {{S}}
Invariante: SZK enthält in jedem Schritt die SZK von G0 .
Sei nun V 0 eine sich im Verlauf ergebende Teilmenge aus V mit v ∈ V 0 und (v, w) der nächsten Kante in
der DFS.
Ist w ∈
/ V 0 , d.h. (v, w) ∈ T , dann erweitere SZK um {w}.
Ist w ∈ V 0 , dann füge (u.U.) mehrere SZKs zu einer zusammen.
Welche SZKs müssen zusammengefügt werden?
Notwendige Bezeichnungen:
• SZK Ki heißt abgeschlossen, wenn alle DFS Aufrufe für Knoten in Ki abgeschlossen sind.
• Die Wurzel von Ki ist der Knoten mit der kleinsten df snum in Ki .
• Eine Teilfolge vonb Knoten, sortiert nach ihrer df snum heißt unfertig, falls ihre DFS-Aufrufe aufgerufen, aber ihre SZK noch nicht abgeschlossen ist.
• Die Menge W enthalte die nach df snum sortierte Folge von Wurzeln der noch nicht abgeschlossenen
SZKs.
Beobachtungen am Beispiel:
?
1. ∀v unfertig: v → g
E
2. @(v, w) ∈ E: v ∈ abgeschlossene Komponenten, w ∈ nicht abgeschlossene Komponenten
Von g ausgehende Kanten:
(g, d) ∈ C: Tut nichts, d liegt in abgeschlossener Komponente.
(g, b) ∈ B:
Vereinigt 4 Komponenten {b, c} {e} {f } {g}
⇒ unfertig
(g, h) ∈ T : Erzeugt eine neue Komponente.
38
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
Proposition:
1. Eine SZK ist maximal in G, wenn sie abgeschlossen ist.
2. Eine SZK ist abgeschlossen, wenn der DFS-Aufruf ihrer Wurzel abgeschlossen ist.
Beweis:
1. Da von der SZK keine unbekannten Kanten mehr ausgehen können, kann keine weitere Kante von
ihr erreicht werden.
2. Trivial.
Verallgemeinerung: Implementiere Menge unf ertig und Menge W (Wurzeln) als Stacks (LIFO, last
in first out), so dass:
(v, w) ∈ T : push(w, unf ertig)
push(w, W )
(v, w) ∈ C ∪ F : Tue nichts.
(v, w) ∈ B: Vereinige alle SZK, ausgehend von SZK(v), deren Wurzeln z df snum[v] > df snum[w]
while dfsnum[top(w)] > dfsnum[w] do
pop(w)
endwhile
D.h. wir entfernen die anderen Wurzeln aus dem Stack.
Beispiel:
⇒ K2 , K3 und K4 werden vereinigt durch pop(w) bis top(w) =Wurzel der SZK(w)
Wenn DF S(v) abgeschlossen ist und v = top(w) ist, wird die SZK ausgegeben (wegen Preposition).
do
z = pop(unfertig)
print(z)
until (z = v)
pop(w)
39
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
7
GRAPHENALGORITHMEN
Korrektheit: Invarianten
(I1 ) @(v, w) ∈ E mit v in den abgeschlossenen Komponenten und w in den nicht abgeschlossenen Komponenten.
(I2 ) Knoten aller nicht abgeschlossenen SZKs (sortiert nach df snum) liegen in einem Pfad in E 0 , ihre
Wurzeln in einem Baumpfad.
(I3 ) Knoten jeder nicht abgeschlossenen Komponente Ki bilden ein “Intervall” im Stack unf ertig, wobei
das zu unterst liegende Element die Wurzel von Ki ist.
Zu zeigen: Invarianten bleiben beim Einfügen von Kanten erhalten.
1. Fall:
(v, w) ∈ T
(I1 ): Es wird keine SZK abgeschlossen
(I2 ): Sei r die Wurzel der Komponente von r. Da die Wurzel einer SZK keinstes df snum und
?
größtes compnum hat, folgt aus Lemma c): v → w
T
?
Wegen (v, w) ∈ T gilt: r → w.
T
Wegen der Induktionsvorraussetzung bleibt I2 erhalten.
(I3 ): Trivial.
2. Fall:
(v, w) ∈ B
(I1 ): Es wird keine SZK abgeschlossen.
(I2 ): Pfad wird verkürzt.
(I3 ): Löschen der obersten Wurzeln vereinigt Intervalle zu einem neuen. Da vorher I2 galt,
bildet dieses Intervall eine eigene Komponente.
Satz: SZKs eines gerichteten Graphen können in O(n + m) berechnet werden.
Bemerkungen:
1. Der Test, ob ein Knoten w ∈ unf ertig ist (für die Frage, ob SZKs vereinigt werden müssen) kann
durch ein bool’sches Array implementiert werden.
2. Jeder Knoten wird höchstens einmal in unf ertig und W aufgenommen.
I N DEN V ORLESUNGEN AM 28.06.2007, 03.07.2007 UND 05.07.2007 KAM EINE P RÄSENTATION ZUM
E INSATZ , DIE SICH AUF DEN FOLGENDEN S EITEN FINDET:
40
www.bioinfoblog.de
Graphentheorie und
Netzwerkanalyse
Eine kleine Reise durch
eine wandlungsfähige
wissenschaftliche Methode
© by Sheep N. Dalton
http://www.thepurehands.org/fractional/
Komplexe Systeme –
überschaubar gemacht als Graphen
• Viele Systeme sind komplex, d.h., dass diese
Systeme aus mehreren Agenten bestehen und
dass das Verhalten des Gesamtsystems von
dem Verhalten der einzelnen Agenten abhängt.
• Beispiele:
– Börse
– Verkehr/Staus
– Soziale Netzwerke, sich darin ausbreitende
Informationen, Krankheiten
– Klima, Globalisierung
Graphen
• Graphen sind mathematische Konstrukte, die aus einer
Menge V={v1, v2, ..., vn} von Knoten (vertices) und einer
Menge E={e1, e2, ...., em} (edges) von Kanten bestehen,
wobei die Kantenmenge E ⊆VxV eine Teilmenge von
VxV ist, also eine Relation (Beziehung).
• Fragen in der realen Welt lassen sich oft sehr gut
beantworten, wenn man die reale Welt durch einen
Graphen approximiert (modelliert), die Frage auf dem
Graphen löst, und die Antwort wieder auf die reale Welt
überträgt.
• Dazu geben wir im Folgenden ein paar Beispiele.
Beispiele: Neuronale Netzwerke
Author(s): (unknown)
Institution: IBM & Ecole Polytechnique
Federale de Lausanne
Year: 2005
URL: http://tinyurl.com/ah3dd
Project Description:
IBM and Switzerland-based Ecole Polytechnique Federale de
Lausanne are working on a joint initiative using the huge
computational capacity of IBM's eServer Blue Gene supercomputer
to create a detailed model of the circuitry in the neocortex - the
largest and most complex part of the human brain, which is
believed to be the center for higher cognitive functions. It is also
the portion of the brain that evolved most recently and that is
unique to mammals.
By expanding the project to model other areas of the brain,
scientists hope to eventually build an accurate, computer-based
model of the entire brain. On its Web site, IBM notes that researchers can learn more about the morphology of the neocortex by
inserting blue dye into each neuron.
The neocortex is organized into six layers and thousands of
columns. The first image shows a fraction of the cells and connections within the neocortex's microcircuitry. The second image
illustrates the pyramidal neurons, which make up 80 percent of
the neurons in the neocortex. © www.visualcomplexity.com, 2007
Beispiele: Straßennetzwerke
Author(s): Sheep N. Dalton
Institution: (unknown)
Year: 2005
URL: http://www.thepurehands.org/fractional/
Project Description:
These images are part of a research done by Sheep N. Dalton in
the context of a paper for the Third Space Syntax conference in
Atlanta, USA. The paper covers a new theory that can perform
new kinds of configurational analysis. The software which performs
the analysis is called "Meanda" (Mean Depth Angular) and was
developed by Dalton.
The project visualizes the network structure of the graph that is
formed from the network of streets. This work is derived from a set
of network theories in architecture known as "Space Syntax". It is
generally found that these colors which are formed from a measurement of graph structure correlate well with observed patterns of
pedestrian movement. The first image illustrates London Radius
infinity Mean Depth. This is a vehicular map so Oxford street has
been removed to represent it's non availability to cars. The second
image shows Amsterdam Mean depth.
© www.visualcomplexity.com, 2007
Beispiele: Metabolismus
Author(s): (unknown)
Institution: Roche
Year: 2003
URL: http://www.expasy.ch/cgi-bin/show_thumbnails.pl
Project Description:
This highly complex diagram is part of Roche Applied Science
"Biochemical Pathways" series of wall charts. Roche created two
informative wall charts, representing metabolic research in many life
science fields, including molecular biology, cell biology, receptors
and immunological interactions, and much more. The charts make it
easy to find the metabolic pathways that most interest a
particular user/researcher.
This digitized version of the pathways map focuses on Metabolic
Pathways and is available at the ExPASy Molecular Biology Server.
© www.visualcomplexity.com, 2007
Beispiele: Internet
Author(s): Stephen G. Eick
Institution: Bell Laboratories
Year: 1993
URL: http://mappa.mundi.net/maps/maps_008/
Project Description:
The arc map displays a 3D network structure as arcs curving smoothly
above a flat map of the world. The data being visualized is Internet
traffic flows between fifty countries, as measured by the NSFNET
backbone in 1993. The colour, thickness and height of the arcs is used
to encode the traffic statistics for particular inter-country links. The arcs
are also partially translucent so as not to completely obscure lines at the
back of the map, while their height above the base map is in relation to
total volume of traffic flowing over a link. This has the effect of making the
most important (high traffic) links, the highest and therefore most visually prominent on the map. The user has considerable
interactive control over the arc map, for example the arc height scaling and translucency can be varied. The map can also
be rotated and scaled, so that the user can view it from any angle.
© www.visualcomplexity.com, 2007
Beispiele: Blogging
Author(s): Lada Adamic, Natalie Glance
Institution: HP Labs, Intelliseek Applied
Research Center (Blogpulse.com)
Year: 2005
URL: http://www.blogpulse.com/papers/2005/AdamicGlanceBlogWWW.pdf
Project Description:
In this paper, the authors studied the linking patterns and discussion topics of political bloggers. The goal was to measure the
degree of interaction between liberal and conservative blogs, and to uncover any differences in the structure of the two communities. Specifically, they analyzed the posts of 40 "A-list" blogs over the period of two months preceding the U.S. Presidential
Election of 2004, to study how often they referred to one another and to quantify the overlap in the topics they discussed, both
within the liberal and conservative communities, and also across communities.
They also studied a single day snapshot of over 1,000 political blogs. This snapshot captured blogrolls (the list of links to other
blogs frequently found in sidebars), and presents a more static picture of a broader blogosphere. Most significantly, the authors
found differences in the behavior of liberal and conservative blogs, with conservative blogs linking to each other more frequently and
in a denser pattern.
The image shown, portraits the community structure of the analyzed political blogs (expanded set), shown using utilizing a GEM
layout in the GUESS visualization and analysis tool. The colors reflect political orientation, red for conservative, and blue for liberal.
Orange links go from liberal to conservative, and purple ones from conservative to liberal. The size of each blog reflects the number
of other blogs that link to it.
© www.visualcomplexity.com, 2007
Die Welt als Graph
• Der Beginn der Graphentheorie wird allgemein
auf 1735 gelegt, als Leonhard Euler die folgende
Frage beantwortete:
Können die sieben Brücken über die Pregel in
Königsberg 'in einem Zug', ohne eine mehrfach zu
überqueren, überquert werden?
Obwohl Euler selbst diese Frage noch nicht mit
graphentheoretischen Methoden bearbeitete,
markiert diese Arbeit den Beginn der
Graphentheorie.
Euler'sche Graphen –
Oder: das ist das Haus vom Nikolaus
• Graphentheoretisch kann man die Frage
wie folgend modellieren:
• Jeder Stadteil wird durch einen Knoten
repärsentiert,
• jede Brücke zwischen den Stadteilen wird
als Kante zwischen den entsprechenden
Knoten repräsentiert.
• Fussnote: Man sollte nicht sagen, dass die Brücke eine Kante
zwischen den Stadtteilen ist, denn dadurch wird die Modellebene
('Kante') mit der realen Welt ('Stadtteile') vermischt.
Reale Welt
Modell
Im Modell:
• wird ein Stadtteil nur noch durch
einen Knoten repräsentiert,
• es zählt nur noch, mit welchen
Stadtteilen er verbunden ist,
• alle weiteren Eigenschaften des
Stadtteils (z.B. weitere Straßen,
Größe, Name des Stadtteils) sind
unerheblich!
Pfade, Wege, Zyklen
• Ein Weg W(v,w) ist eine geordnete Teilmenge, d.h., eine Folge von
Kanten W(v,w)={e1, e2, ...., ek} aus E mit e1=(v, v1), ek=(vk-1, vk), und
für alle 2 ≤ i ≤ k-1, ei=(vi-1, vi). Alle Elemente müssen aus E sein.
• Ein Zykel ist ein Weg mit gleichem Anfangs- und Endknoten.
• Ein Zykel ist ein einfacher Zykel, wenn kein Knoten mehrfach in ihm
enthalten ist. Ein Zykel ist ein trivialer Zykel, wenn er (in einem
ungerichteten Graphen) aus zweimal derselben Kante besteht.
• Ein Pfad ist ein Weg, in dem kein Knoten mehr als einmal
vorkommt.
• Die Länge eines Pfades ist gleich der Anzahl der in ihm enthaltenen
Kanten.
• Ein Graph ist zusammenhängend, wenn es für alle Paare von
Knoten einen sie verbindenden Pfad gibt.
Reale Welt
Modell
Können die sieben Brücken über die
Pregel in Königsberg 'in einem Zug',
ohne eine mehrfach zu überqueren,
überquert werden?
Dieselbe Frage auf Modellebene:
Können wir einen Pfad finden, der
in demselben Knoten anfängt und
endet und alle Kanten des Knotens
genau einmal enthält?
Die Antwort
•
Eine sogenannte 'Euler-Tour' ist genau dann möglich, wenn der
Graph zusammenhängend ist und jeder Knoten eine gerade Anzahl
von Kanten (Grad) hat.
•
Beweis:
–Wir zeigen die Äquivalenz der folgenden Begriffe:
1.
2.
3.
•
Ein Graph hat eine Euler-Tour
Alle Knoten des Graphen haben geraden Grad.
Die Kanten von G können in (nicht-triviale) Zykel partitioniert werden.
Zur Erinnerung: Eine Partitionierung zerlegt eine Menge M in
Teilmengen M1, M2, ..., Mk, so dass die Vereinigung aller
Teilmengen M ergibt und dass der Schnitt je zweier Teilmengen Mi,
Mj, i != j leer ist.
1 Y2
Wenn es eine Euler-Tour gibt, und ein Knoten
k-mal darin vorkommt, dann wird der Knoten
über k Kanten betreten, und über k Kanten
verlassen. Also hat der Knoten geraden Grad.
2Y3
• Per Induktion über die Anzahl der (einfachen) Zyklen k
im Graphen
– Induktionsanfang: Wenn es keinen Zykel im Graphen gibt, ist
der Graph ein Baum. Da ein Baum mit mindestens einer Kante
mindestens zwei Blätter hat (leicht zu sehen), darf der Baum
keine Kante haben. Y Jeder Knoten hat Grad 0, der Baum lässt
sich (definitionsgemäß) in Zykel partitionieren.
– Induktionsschritt: Sei nun G ein Graph mit k>0 Zykeln. Sei nun C
einer dieser (einfachen) Zykel, betrachte G-C (entferne die
Kanten aus C in G). Dadurch hat jeder Knoten entweder
denselben Grad wie vorher oder einen um zwei verminderten
Grad. Der Graph hat einen Zykel weniger. Wegen
Induktionsanfang ist damit der Beweis gemacht. (Überlegen Sie
sich, was passiert, wenn durch das Wegnehmen des Zykels der
Graph in Komponenten zerfällt!)
3Y1
• Sei nun G in die Zykel C= C1, C2, ..., Cm
partitionierbar.
• Weil G zusammenhängend ist, muss Zykel C1
mit mindestens einem Zykel C2 einen
gemeinsamen Knoten haben. Vereinige diese
beiden Zykel zu C', füge C' zu C zu, und lösche
C1 und C2 aus C.
Dabei wird keine Kante mehrfach gelaufen!
• Nach m-1 dieser Vereinigungsschritte besteht C
nur noch aus einem Zykel.
~
Welche Florentinische Familie war
die wichtigste im alten Florenz?
• Eine schon sehr alte Frage aus den
Sozialwissenschaften ist: gegeben ein soziales
System, wo ist der Dreh- und Angelpunkt des
Systems, wer ist der/die Wichtigste?
• Weil soziale Systeme komplex sind, konzentriert
man sich auf eine Beziehung der sozialen
Entitäten, z.B., wer hat wen gewählt, wer ist in
welchem Aufsichtsrat, etc.
Florentinischer Heiratsmarkt
Kürzeste Pfade und Distanzen
• Ein zusammenhängender Teilgraph G'=(V'⊆V, E') mit
E' = {e=(v,w) aus E mit v, w in V'}
ist eine Zusammenhangskomponente, wenn er nicht
mehr erweitert werden kann, ohne dass der
Zusammenhang verloren geht.
• Ein kürzester Pfad P(v,w) zwischen v,w ist ein Pfad
minimaler Länge. Wenn v und w in unterschiedlichen
Zusammenhangs-komponenten liegen, gibt es keinen
solchen Pfad.
• Die Distanz d(v,w) zwischen v und w ist definiert als die
Länge ihres kürzesten Pfades. Existiert dieser nicht, ist
die Distanz definitionsgemäß ∞.
• Der Durchmesser D(G) eines Graphen ist definiert als
die maximale Distanz zweier Knoten in ihm.
Zentralitätsmaße
• Verschiedene Maße, z.B.
– Grad (wer am meisten Kanten hat, ist der Wichtigste)
– Stress Zentralität: Der ist am Wichtigsten, über den
die meisten kürzesten Pfade laufen.
– Exzentrizität: Der ist am Wichtigsten, der die kleinste
maximale Distanz zu allen anderen Knoten im
Graphen hat.
– Nähe: Der ist am Wichtigsten, der die kleinste
Gesamtdistanz zu allen anderen Knoten im Graphen
hat.
– ...
Was ist die wichtigste Seite im
Web?
• Abhängig von der Suchanfrage.
• Meistens erstmal textuelle Suche nach Seite mit
entsprechenden Stichworten.
• Dann Teilgraphaufbau, der die umgebenden
Seiten mit einbezieht (bis zu einer bestimmten
Distanz).
• Dann z.B. 'Hubs and Authorities'-Analyse:
– Wer zeigt auf die meisten anderen Seiten mit diesen
Textbausteinen? Y Hub
– Auf wen zeigen die meisten anderen Seiten? Y
Authority
Wer ist der am besten vernetzte
Wissenschaftler?
• Newman fragte sich 199X, welcher
Wissenschaftler der am besten vernetzte
Wissenschaftler ist.
• Dazu untersuchte er das Co-AuthorshipNetzwerk des Online-Publikations-Archives
ArXiv im Sektor condensed matter in Bezug auf:
– meisten Publikation pro Autor;
– meisten Co-Autoren per Autor;
– größte Betweenness; etc.
Wie können wir Proteine
annotieren?
• Proteine sind biologische Substanzen mit einer
bestimmten Funktion, die teilweise von ihrer Struktur und
ihren Wechselwirkungen mit anderen Proteinen
abgeleitet werden kann.
• Protein-Protein-Interaktionsnetzwerke repräsentieren
diese Wechselwirkungen.
• Durch das Auffinden von dichten Teilgraphen (sog.
Clustern) können Gruppen von Proteinen gefunden
werden, die oft auch dieselbe Funktion in der Zelle
haben. Wenn ein neues Protein in eine solche Gruppe
fällt, können gezielte Experimente schnell zeigen, ob das
neue Protein auch dieselbe Zellfunktion hat.
Wie gut sind die AmazonEmpfehlungen?
• Auf jeder Seite von Amazon findet man
Links unter dem Titel 'Kunden, die diesen
Artikel kauften, kauften auch'.
• Diese Links kann man crawlen und die
entstehenden Netze analysieren.
Wie empfindlich sind soziale Netzwerke
gegenüber Krankheiten?
• Wie können wir soziale Netzwerke modellieren?
• Erste Idee: Zufallsgraphen, jede Kante hat
dieselbe Wahrscheinlichkeit p zu existieren.
• Ein solcher Graph hat für p ~ log n/n einen
Durchmesser von O(log n).
• Die Wahrscheinlichkeit, dass zwei Nachbarn
eines Knoten auch untereinander eine Kante
haben, ist p.
Small-Worlds
• Diese Wahrscheinlichkeit ist in sozialen
Netzwerken viel höher als die
Wahrscheinlichkeit, dass wir irgendeinen
Menschen 'weit weg' von uns kennen.
(Gemeinsame Parties, Kollegen, Sportvereine).
• In sozialen Netzwerken ist also der sogenannte
Clusteringkoeffizient viel höher.
• Clusteringkoeffizient ist definiert als:
Small-World-Model
• Um ein Netzwerk als Zufallsgraphen zu
modellieren, sollte die Anzahl der Knoten
gleich sein, die der erwarteten Kanten
gleich der Anzahl der echten Kanten.
• Also:
– Bernoulli-Experiment für jede Kante,
– erwartete Anzahl von Kanten
– Für gegebenes n und m p ausrechnen
Reale Netzwerke
• Wenn p nach der auf der vorangehenden
Folie ausgerechnet wird, haben reale
Netzwerke einen viel höheren (bis zu 1000
mal höheren) Clusteringkoeffizienten als
der entsprechende Zufallsgraph.
– Beachte: Clusteringkoeffizient in
Zufallsgraphen ist gleich p!
• Neues Modell ist notwendig!
Realwelt-Modelle
• Ein anderes Autorenteam konnte zeigen, dass
Zufallsgraphen auch in einem anderen Aspekt
reale Netzwerke nicht gut modellieren.
• Gradverteilung: Zeichnet man die
Wahrscheinlichkeit P(k), einen Knoten mit Grad
k aus V zu ziehen gegen den Grad k auf, dann
ergibt sich bei Zufallsgraphen eine
Normalverteilung.
• Bei den meisten realen Netzwerken findet man
eine Verteilung P(k) ~ k-γ, sog. Power-Law oder
skalenfreie Gradverteilung.
Realwelt-Modelle
• Es gibt viele neue Realwelt-Modelle.
• Diese dienen z.B. dazu, die Verbreitung von
– Informationen in P2P-Netzwerken,
– Krankheiten in sozialen Netzwerken,
– kaskadierenden Ausfällen von Energiekraft-werken in
Stromversorgungsnetzwerken zu analysieren.
• Man kann mit ihnen aber auch versuchen,
– Wichtige Aktivierungsmuster in Genaktivationsnetzwerken zu
finden;
– die wichtigsten metabolischen Moleküle zu bestimmen;
– die Empfindlichkeit von Netzwerken auf verschiedene Arten von
Attacken zu testen: es stellt sich heraus, dass Zufallsgraphen
weniger anfällig für (terroristische) Attacken sind, während
skalenfreie Netzwerke weniger anfällig für zufällige Ausfälle sind.
Vorlesungsstoff
• Wir werden basale Algorithmen vorstellen, auf
denen diese und andere Algorithmen aufbauen
(z.B. in Algorithmen und Komplexität,
Bioinformatik)
• Insbesondere:
–
–
–
–
Topologische Sortierung
Berechnung kürzester Wege,
Minimaler Spannbaum/Single Linkage Clustering,
Graph-Durchwanderungsalgorithmen (DFS/BFS)
Lehrziele der Vorlesung
Algorithmen
•
Sehen Sie diese Folien als Motivation für die
Lehrziele in Algorithmen:
–
Überblick über grundlegende Algorithmen und
Datenstrukturen;
•
–
Ohne diese grundlegenden Algorithmen, z.B. die
Breitensuche in Graphen können die vorgestellen
Fragestellungen nicht beantwortet werden.
Einüben und Verstehen der theoretischen Analyse
von Algorithmen;
•
Nur mit Hilfe der theoretischen Analyse von Algorithmen
können wir effiziente von nicht-effizienten Algorithmen
unterscheiden. Bei Netzwerkgrößen von bis zu 500
Millionen Knoten durchaus wichtig!
Lehrziele der Vorlesung
Algorithmen
– Formalisierung von algorithmischen Fragestellungen;
• Die an uns herangetragenen Fragestellungen sind oft unklar
und schwammig. Erst eine Formalisierung erlaubt einem
Team von Programmierern eine Lösung zu finden, da
dadurch die Mehrdeutigkeit natürlichsprachlicher
Formulierungen verringert wird.
– Design von effizienten Algorithmen und
Datenstrukturen;
• Die Kenntnis einer breitgefächerten Sammlung von
Algorithmen und Datenstrukturen befähigt Sie dazu, neue
Lösungen für neue Probleme zu finden, oder eine
Verbindung zwischen zwei Problemen zu finden, so dass sie
das zweite mit Verfahren des ersten lösen können.
– Verbesserung der Programmierfähigkeiten.
• Selbst ein effizienter Algorithmus ist nur so gut wie seine
Implementierung!
In eigener Sache
Studienarbeiter und Bachelorstudenten sind
zu diesen Themen (und anderen, wie
Graphenzeichnen und jeglichem algorithmischen Themengebiet) jederzeit herzlich bei
uns willkommen! ☺
7.4 Kürzeste und Billigste Wege in Graphen
Sei G = (V, E) ein gerichteter Graph mit Kostenfunktion
c: E
R.
Sei p = ((v0,v1) ..., (vk-1, vk) Pfad von v0 = v nach vk = w.
Dann heißt k −1
c( p ) := ∑ c(vi , vi +1 )
i =0
Kosten des Pfades von v nach w.
dist(v, w) = inf {c(p) | p ist Pfad von v nach w} heißt Entfernung
oder Distanz zwischen v und w.
1
Beispiel:
2
–1
4
1
2
3
3
4
dist(1,2) =
dist(3,1) =
dist(4,6) =
2
6
–6
5
3
2
Beispiel:
2
–1
4
1
2
3
3
4
dist(1,2) = – 1
dist(3,1) = ∞
dist(4,6) = – ∞ , da
Pfad (4,(5,6,4)i) Kosten 3 – i
hat für alle i ≥ 0.
Kantenfolge!!
negativer Zyklus
2
6
–6
5
3
3
3 grundsätzliche Problemstellungen:
1 single pair shortest paths
(kürzeste Wege zwischen einem Knotenpaar)
2 single source shortest paths
(kürzeste Wege von einem Knoten aus)
3 all pairs shortest paths
(kürzeste Wege zwischen allen Knotenpaaren)
4
7.3.1 Single Source Shortest Paths
Sei s der „Quellknoten“. G = (V, E).
Gesucht ist für alle Knoten u ∈V
∞, falls kein Pfad von s nach u in G,
dist (s, u ), sonst.
δ (u ) := 
Lemma:
Sei u ∈ V . Dann gilt:
i) δ (u ) = −∞ gdw. u ist erreichbar aus negativem
Zyklus, der von s aus erreichbar ist.
ii) δ (u ) ∈ R ⇒ ∃ billigster einfacher Pfad von
s nach u mit Kosten δ (u ) .
5
Beweis:
i) "⇐" : klar!
"⇒" :
6
ii)
7
7.4.1.1 Der geg. Graph G = (V, E) ist azyklisch.
Bsp.:
2
2
3
5
2
5
s
–1
3
2
6
4
1
δ(s) =
δ(2) =
δ(3) =
δ(4) =
δ(5) =
δ(6) =
8
Nachfolgender Algorithmus setzt voraus, dass der Graph
topologisch sortiert ist, „also“ V = {1, 2, ... , n}.
Algorithmus:
d(s)
0;
//d von s nach s ist 0
Pfad(s)
Ø; //Pfad wird für jeden Knoten als Liste implementiert
for all v ∈ V \ {s} do d(v)
//Initialisierung
∞ od;
for v = s + 1 to n do
//für alle 'Nachfolger' von s
d(v) min {d(u) + c(u,v) | (u,v) ∈ E} //setze d(v)
//auf minimalen Wert
//Sei u* der Vorgänger mit
Pfad(v)
Pfad(u*) ° (u,v)
//d(u*)+c(u*,v) minimal
od
9
Satz:
Nach Ausführung von obigem Algorithmus gilt
∀v ∈ V
1) d (v ) = δ (v )
2) d (v ) < ∞ ⇒ Pfad(v) ist billigster Weg
von s nach v.
3) Algorithmus hat Laufzeit O( n + m), wobei
n = |V| und m = |E|.
Beweis:
Korrektheit ( 1) + 2) ): Induktion über v
v < s: δ (v ) = ∞, da v von s aus nicht erreichbar.
d (v ) = ∞, da nach Init. nicht mehr verändert
v = s: δ (v ) = d (v ) = 0. Pfad(s) = s ist einziger Weg.
10
v > s:
11
Laufzeit:
Topologisches Sortieren kostet Zeit O( n + m ).
Initialisierung: O(n)
„Hauptteil“: Komplexität wird im Wesentlichen bestimmt durch
∑ In(v ) = m ,
v∈V
also O( n + m ).
12
7.4.1.2 Alle Kantenkosten nichtnegativ (d.h. ∀e ∈ E , c(e) ≥ 0),
Zyklen erlaubt
Dijkstras Algorithmus:
Anmerkung:
Nachfolgend werden nur Distanzen berechnet;
eigentliche Pfadberechnung analog zu vorherigem Algorithmus.
Idee: Für Menge S von Knoten mit bereits bestimmtem kürzesten
Pfad muss es einen Knoten x ∈ V \ S geben, so dass
der kürzeste Weg von s nach x über die Knoten in S geht
und dann noch eine Kante aus S nach x benutzt.
Genauer: x ist der Knoten, der für alle u ∈ S den Ausdruck
δ (u ) + c (u , x ) minimiert.
13
Nachfolgend:
S := Menge der Knoten u mit bekanntem δ(u ).
S ′ := Menge der Knoten aus V \ S , die Nachbarn in S haben
Algorithmus:
S ← {s}; d (s ) ← 0;
S ′ ← OutAdj(s );
for all u ∈ S ′ do;
//Initialisiere S, d(s)
//S' entspricht am Anfang den Nachbarn von s
//für diese initialisiere d'(u)
d ' (u ) ← c(s, u );
for all u ∈ V − (S ∪ S ′) do
//für die anderen setze es auf +∞
d ' (u ) ← ∞;
14
while S ′ ≠ o/ do
x ← derjenige Knoten aus S ′ mit minimalem d'-Wert;
d ( x ) ← d ' ( x );
S ← S ∪ {x};
S ′ ← S ′ \ {x};
for all u ∈ OutAdj ( x ) do
if u ∉ S
then S ′ ← S ′ ∪ {u };
d ' (u ) ← min {d ' (u ), d ( x ) + c ( x , u )}
fi
od
od
15
Beispiel (Dijkstra, Ungerichteter Graph):
S=
S´=
d(s) =
d´(C) =
d´(D) =
d´(E) =
S=
S´=
d(D) =
d´(C) =
d´(E) =
d´(B) =
3 A
1
B 4
1
4
2 C
3
D 1
2
1
2
0 s
5
E 3
S=
S´=
d(E) =
d´(B) =
S=
S´=
d(C) =
d´(B) =
d´(E) =
d´(A) =
S=
S´=
d(A) =
d´(B) =
d´(E) =
S=
d(B) =
16
Beispiel (Dijkstra, Ungerichteter Graph):
S = {s, D, C},
S´={E, B, A}
d(C) = 2,
d´(B) = 5,
d´(E) = 3,
d´(A) = 3
S = {s},
S´={C, D, E} 3
1
A
B 4
d(s) = 0,
d´(C) = 2,
1
4
d´(D) = 1,
3
D 1
2 C
d´(E) = 5
1
2
2
S = {s, D, C, A},
S = {s, D},
S´={E, B}
0 s
E 3
5
S´={C, E, B}
d(A) = 3
d(D) = 1,
d´(B) = 4,
S = {s, D, C, A, E},
d´(C) = 2,
d´(E) = 3
S´={B}
d´(E) = 3,
d(E) = 3
S = {s, D, C, A, E, B},
d´(B) = 5
d´(B) = 4,
d(B) = 4,
17
Beispiel (Dijkstra, Gerichteter Graph):
1 1
10
4 5 4 46
B
0 s 1
H
1
F
3
7 7 5
2 2 C 2
2
3
3
3 6 3 G
5
2 A
J
5
1
E 1 1
2
3
2
I
D 7 10 1
K
8 84
5 5
9
1
10
2 L ∞
10 9 9
12 11 11
9
18
Lemma:
Sei x ∈ S ′ so gewählt, dass d ' (x ) minimal ist.
Dann gilt d ' (x) = d (x).
Beweis:
Sei p ein billigster Weg von s nach x derart, dass alle
Kanten bis auf die letzte zwischen Knoten aus S sind.
Angenommen, es gäbe einen billigeren Weg q von s nach x.
q muss einen ersten Knoten v in V \ S haben und nach Wahl
von x ist d ′(v ) ≥ d ′( x ).
Da alle Kanten nichtnegativ sind, gilt aber
c(q ) ≥ d ' (v ) ≥ d ' (x ) = c( p ),
ein Widerspruch zu der Aussage, dass q ein billigerer
Weg als p sei.
19
Zur Laufzeit:
Implementiere S und S ′ als Bitvektoren
und d und d' als Arrays.
•Aufwand für „ for all u ∈ OutAdj( x ) “:
∑ OutAdj( x ) = O(m + n ).
x∈V
•n-maliges Minimieren über S ′ : O(n ² ).
Insgesamt ergibt sich Laufzeit O(n²+m),
für dichte Graphen (m ≈ n ² ) ausreichend.
20
Alternativ:
Speichere S ′ in Heap (balancierter Baum), gemäß
d' -Werten geordnet.
Damit Laufzeit O((m+n)log n),da nun Einfügen
und Löschen in S ′ je O(log n ) Zeit kostet.
Für dünne Graphen ist dies eine Verbesserung.
21
Satz:
Mit Hilfe des Algorithmus von Dijkstra läßt sich das
Single Source Shortest Path Problem in Laufzeiten
O(n² ) bzw. O((m + n ) log n ) lösen.
Mitteilung:
Mit Hilfe sogenannter Fibonacci-Heaps läßt sich die
Laufzeit des Algorithmus von Dijkstra asymptotisch
zu O(n log n + m) verbessern.
22
7.4.1.3 Negative Kantenkosten erlaubt, aber keine negativen Zyklen.
Bellman-Ford-Algorithmus
Das „Entspannen einer Kante (v,w)“ bezeichnen wir mit
Relax ((v,w)):
δ (w) ← min{δ (w), δ (v ) + c(v, w)}
Offensichtlich: Das Entspannen einer Kante kann den
δ-Wert niemals erhöhen.
23
Lemma:
Falls für alle w∈ V vor dem Entspannen einer beliebigen
Kante (v,w) gilt, dass d(w) ≥δ(w) , dann gilt dies auch
hinterher.
Beweis: (Induktion über Kanten)
Jeder Weg von s nach v zusammen mit Kante (v,w)
ergibt Weg von s nach w.
Deshalb δ (v ) + c (v, w ) ≥ δ (w ).
Weiterhin: δ (v) + c(v,w) ≤ d (v) + c(v,w)
⇒ δ (w) ≤ d (v ) + c(v, w)
⇒ δ (w) ≤ d (w) falls (v,w) „echt“ relaxiert.
24
Algorithmus:
d (s ) ← 0;
for all v ≠ s do
d (v ) ← ∞
while „ möglich“ do
Entspanne Kanten
od
Beobachtung: d(u) wird immer kleiner, unterschreitet aber nie δ(u) .
25
Offen bleibt noch die Frage nach der „Entspannungs-Reihenfolge“,
sodass d schnell gegen δ konvergiert.
Lemma:
Sei w ∈ V und sei δ (w) < ∞ und sei (v, w) die letzte Kante
auf dem billigsten Weg von s nach w.
Dann gilt:
Falls (v,w) entspannt wird, nachdem d(v) = δ(v) geworden
ist, so ist danach d(w) = δ(w).
Beweis: nach Definition der Kante (v,w).
26
Algorithmus:
d (s ) ← 0;
for all v ≠ s do
d (v ) ← ∞;
for i ← 1 to n − 1 do
for all (v, w) ∈ E do
Relax ((v, w));
Bem.: im Beispiel spielt
die Reihenfolge der Kanten
in der for all-Schleife eine
Rolle, die Aussagen gelten
aber für alle Reihenfolgen
Lemma:
Für i=0,..., n-1 gilt:
Nach dem i-ten Durchlauf der for-Schleife ist d (w) = δ(w)
für alle w∈ V , für die es einen billigsten Pfad mit i Kanten
von s nach w gibt.
27
Beweis:
Induktion über i:
i = 0 : d (s ) = δ(s ), da es keine negativen Zykel gibt.
i → i +1:
Sei w der Knoten mit billigstem Weg von s nach w mit
i+1 Kanten und sei (v,w) die letzte Kante auf diesem Weg.
Also gibt es billigsten Weg von s nach v der Länge i und
nach Induktionsannahme ist nach dem i-ten Durchlauf
der for-Schleife d (v ) = δ(v ) . Im (i+1)-ten Durchlauf wird
insbesondere (v,w) entspannt:
⇒ d (w) = d (v ) + c((v, w))
= δ(v ) + c((v, w))
= δ( w )
28
Korollar:
Nach dem (n-1)-ten Schleifendurchlauf gilt für alle v aus V,
dass d (v ) = δ(v ).
Beweis:
Nach obigem Lemma und der Annahme der Nichtexistenz
negativer Zyklen folgt, dass alle billigsten Wege aus
höchstens n-1 Kanten bestehen.
Insgesamt:
Satz:
In Laufzeit O(n ⋅ m ) läßt sich das Single Source Shortest Path
Problem lösen, falls der Graph keine negativen Zyklen enthält.
29
Beispiel (Bellmann-Ford, Gerichteter Graph, positive Kanten):
1
B
10
5 4
6
0 s 1
H
1
F
3
7
2 C 2
5 2 L ∞
2
6
G
3
3
3
3
5
2 A
J
5
1
E 1 1
10 9
2
3
I
D 7 10 1
4
K 12 11
8
5
9
1
4
i = 1, i = 2, i = 3, i = 4, i = 5,
i = 6, i = 7, i = 8,
30
Beispiel (Bellmann-Ford, Gerichteter Graph, negative Kanten,
aber keine negativen Zyklen):
1
7
1
4 5 1
B
6
0 s 1
H
1
F
3
4
-1 C 2
-5 2 L ∞
2
6
G
-3
-3
3
3
5
2 A
J
-5
1
E -1 1
1
2
3
I
D 7 7 1
4
K 3
5
5 4
4
i = 1, i = 2, i = 3, i = 4, i = 5,
i = 6, i = 7, i = 8,
31
Beispiel (Bellmann-Ford, Ungerichteter Graph, positive Kanten):
1
0
1
A
6 5
6
6
2
s
2
4
B
4 3
C
5
1
D
12 11 10
E
4
9 7 6
i = 1, i = 2, i = 3, i = 4, i = 5,
Warum braucht der Algorithmus hier n-1 Iterationen
bis zur Konvergenz?
Welches wäre der einfachste Graph mit dieser Eigenschaft?
32
7.4.1.4: Graphen mit negativen Zyklen
Algorithmus:
1
2
Führe zuerst die n-1 for-Schleifendurchläufe des Algorithmus von Bellman-Ford aus und merke in d1 die so
erzielten d-Werte.
Führe n weitere for-Schleifendurchläufe aus und speichere
das Ergebnis in d2.
A1: Wie kann man nun erkennen, ob ein Knoten durch einen
negativen Zyklus mit s verbunden ist?
33
Lemma:
Für w ∈ V gilt :
i) d 2 (w) = d1 (w) ⇒ δ(w ) = d1 (w)
ii) d 2 (w) < d1 (w) ⇒ δ(w ) = −∞
Beweis:
34
Bemerkung:
Wenn sich nach nur einem weiteren Durchlauf der
for-Schleife nach Abschluss von 1 noch etwas ändert, so
gibt es einen negativen Zyklus, sonst aber nicht.
Um aber alle Knoten entdecken zu können, die durch einen
negativen Zykel von s aus erreichbar sind, benötigt man in 2
insgesamt n Durchläufe.
A2: Geben Sie eine Graphenfamilie an, bei der das so ist.
35
7.4.2 All Pairs Shortest Paths (Floyd-Warshall)
Annahme: Keine negativen Zyklen.
V = {1,2,..., n}
Für i, j ∈ V und 0 ≤ k ≤ n definiere
δ k (i, j ) := Kosten des billigsten Weges von i nach j ,
dessen innere Knoten ≤ k sind.
Beispiel:
δ 0 (1,4 ) =
δ1 (1,4) =
δ 2 (1,4) =
δ 3 (1,4 ) =
δ 4 (1,4) =
4
2
2
2
1
-3
3
4
5
A3: Füllen Sie die Werte links für den
obenstehenden Graphen aus.
36
Also:
c(i, j ), falls (i, j ) ∈ E.

δ 0 (i, j ) =  0
, falls i = j.
 ∞ , sonst.

A4: Wann haben wir die Kosten für den billigsten Weg von i nach j
garantiert berechnet?
A5: Wie berechnet sich
δ k aus δ k-1 ?
37
A4: Wann haben wir die Kosten für den billigsten Weg von i nach j
garantiert berechnet?
δ n (i, j ) = δ(i, j ) = Kosten des billigsten Weges von i nach j ,
da nach n Schritten (ohne negative Zyklen) jeder Knoten, der
von s aus erreichbar ist, auf seinem billigsten Weg erreicht wurde.
A5: Wie berechnet sich δ k aus δ k-1 ?
2 Möglichkeiten:
Entweder k Teil eines billigeren
Weges oder nicht:
δ k-1 (i, j )
i
δ k-1 (i, k )
k
j
δ k-1 (k , j )
Also gilt: δ k (i, j ) = min{δ k −1 (i, j ), δ k −1 (i, k ) + δ k −1 (k , j )}
38
Beispiel (Floyd-Warshall, Ungerichteter Graph, positive Kanten):
6
2
1
6
2
1
2
4
3
4
1
4
5
5
D0=
6
D1 = D0
D2=
D3=
D4=
u.s.w.
39
Beispiel (Floyd-Warshall, Ungerichteter Graph, positive Kanten):
6
2
1
6
2
1
2
4
D1 = D0
0 1
1 0
D2= 3 2
7 6
u u
u u
3
3
2
0
2
5
u
7
6
2
0
1
6
u
u
5
1
0
4
5
u
u
u
6
4
0
4
2
0
2
5
u
u
6
2
0
1
6
u
u
5
1
0
4
u
u
u
6
4
0
0 1 3
1 0 2
D4= 3 2 0
5 4 2
6 5 3
11 10 8
5
4
2
0
1
6
6
5
3
1
0
4
11
10
8
6
4
0
4
1
4
5
0
1
D3= 3
5
8
u
D0=
6
1
0
2
4
7
u
3
2
0
2
5
u
5
4
2
0
1
6
8
7
5
1
0
4
u
u
u
6
4
0
0
1
4
u
u
u
1
0
2
6
u
u
u.s.w.
40
Algorithmus (Floyd-Warshall):
for all i , j ∈ V do
A6: Geben Sie den
Algorithmus an, der δn(i,j)
für alle i,j berechnet.
c (i , j ), falls (i , j ) ∈ E

δ 0 (i , j ) ←  0
, falls i = j
∞
, sonst
;

od
A7: Welche Laufzeit hat der Algorithmus?
41
Algorithmus (Floyd-Warshall):
for all i , j ∈ V do
c (i , j ), falls (i , j ) ∈ E

δ 0 (i , j ) ←  0
, falls i = j
∞
, sonst
;

od
for k = 1 to n do
for i = 1 to n do
for j = 1 to n do
δ k (i , j ) ← min { δ k −1 (i , j ), δ k −1 (i , k ) + δ k −1 (k , j )}
od
od
od
A7: Laufzeit: O(n³)
42
Alternativer Algorithmus:
Benutze Algorithmus von Dijkstra bzw. Bellman-Ford
Idee:
Führe n-mal für alle möglichen Startknoten Bellman-FordAlgorithmus aus.
Laufzeit : O(n ⋅ nm )
Beobachtung:
Es reicht sogar, einmal Bellman-Ford und (n-1)-mal
Dijkstra auszuführen.
Laufzeit : O(n ⋅ (n + m ) log n )
43
7.4.3 All Pairs Shortest Paths (Matrix-Form)
Annahme: Keine negativen Zyklen.
G = (V , E ), V = {1,2,..., n}
Lemma: Wenn ein Pfad von i über k nach j der
kürzeste Pfad von i nach j ist, dann sind auch die Pfade von
i nach k und von k nach j jeweils kürzeste Pfade.
A8: Beweis
44
Sei G als Adjazenzmatrix W = (w((i,j))) repräsentiert.
Sei p ein kürzester Pfad von i nach j mit m Kanten.
Es gilt: m < n.
Falls i = j, dann hat p die Länge 0 und keine Kanten.
Falls i ≠ j, dann zerlegen wir p in Pfad p´ von i nach
k und Kante (k, j), wobei p´ dann m-1 Kanten hat. Es
gilt:
δ (i, j ) = δ (i, k ) + wkj
45
Sei lij(m ) der kürzeste Pfad zwischen Knoten i und j,
der höchstens m Kanten hat. Für m = 0 gilt
(0)
ij
l
 0 falls i = j
=
sonst
∞
Für m ≥ 1 berechnen wir
(
{
+w }
lij( m ) = min lij( m −1) , min1≤ k ≤ n lik( m −1) + wkj
{
= min1≤ k ≤ n lik( m −1)
})
denn wjj = 0 für alle j
kj
Da ein kürzester Weg von i nach j höchstens n-1
Kanten hat, gilt δ (i, j ) = lij( n −1) = lij( n ) = lij( n +1) = ...
46
(m )
Wir berechnen also die lij in einer Folge von
Matrizen
L(1), L(2), ... L(n-1), mit L(m) = ( lij(m ) ).
Algorithmus Slow-All-Pairs-Shortest-Paths (W)
1) L(olc) := W
Zeitaufwand: O(n4)
2) for m := 2 to n-1 do begin
3) for i := 1 to n do
Verwendung von
4)
for j := 1 to n do begin
nur zwei Matrizen
5)
lij(new) := ∞
L(new) und L(old)
6)
for k := 1 to n do
7)
lij( new) := min(lij( new) , lik( old ) + wkj )
8)
end
9) L(old) := L(new)
10) end
4
Beispiel:
2
2
1
-3
 0 4 − 3 ∞
∞ 0 ∞ 2 
(1)

L =
∞ 2 0 5 


∞
∞
∞
0


 0 − 1 − 3 1
∞ 0 ∞ 2 
( 3)

L =
∞ 2
0 4


∞
∞
∞
0


2
L( 2 )
3
47
4
5
 0 −1 − 3
∞ 0 ∞
=
∞ 2
0

∞ ∞ ∞
2
2
4

0
Bemerkung:
Laut Cormen et al. sieht dieser Algorithmus ein
bisschen aus wie der Algorithmus zur Matrixmultiplikation und wird daher von den Autoren
auch 'Matrixmultiplikaitonsalgorithmus' genannt.
Übung: Matrixmultiplikationsalgorithmus
aufschreiben!!
48
Beispiel (Matrix"multiplikations"algorithmus):
2
1
6
2
4
0 1 3
1 0 2
L2 = 3 2 0
6 4 2
9 7 3
u 12 8
3
6
4
2
0
1
5
9 u
7 12
3 8
1 5
0 4
4 0
4
6
2
1
5
0
1
L1=W= 4
u
u
u
1
5
6
4
0 1 3
1 0 2
L3 = 3 2 0
5 4 2
7 5 3
1210 7
5
4
2
0
1
5
7 12
5 10
3 7
1 5
0 4
4 0
1
0
2
6
u
u
4
2
0
2
5
u
u
6
2
0
1
6
u
u
5
1
0
4
u
u
u
6
4
0
0 1
1 0
L4 = 3 2
5 4
6 5
11 9
5
L : 10
3
2
0
2
3
7
5
4
2
0
1
5
6 11 10
5 9
3 7
1 5
0 4
4 0
49
Geht es auch schneller? Ja, durch Quadrierung!
Bisher hatten wir berechnet:
L(1) = L(0) * W = W
L(2) = L(1) * W = W2
L(3) = L(2) * W = W3
...
L(n-1) = L(n-2) * W= Wn-1
Jetzt berechnen wir schneller:
L(1) =
=W
L(2) = W * W
= W2
L(4) = W2 * W2 = W4
L(8) = W4 * W4 = W8
...
50
Algorithmus Fast-All-Pairs-Shortest-Paths (W)
1) L(old) := W
2) m := 1
Zeitaufwand: O(n3 log n),
3) while m < n-1 do
das ist aber immer noch
4) for i := 1 to n do
langsamer als der
5)
for j := 1 to n do begin Floyd-Warshall-Algorithm.
lij(new) := ∞
6)
7)
for k := 1 to n do
lij( new) := min(lij( new) , lik( old ) + lkj( old ) )
8)
9)
end
10) m := 2m
11) L(old) := L(new)
12) endwhile
51
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
8
8
HASHING
Hashing
In einem Universum U = [0, . . . , N − 1] sei S ⊆ U die zu verwaltende Menge.
Zur Verfügung stehen sollen die Operationen “Zugriff ”, “Einfügen” und “Streichen”.
Hashtafel: T [0, . . . , m − 1]
Hashfunktion: h : U → [0, . . . , m − 1], a → T [h(a)]
Beispiel: N = 50, m = 3, S = {2, 21}
h(x) = x mod 3
21
0
1
2
2
Problem: Kollisionen, also h(x) = h(y) für x 6= y, z.B. x = 2, y = 20
Ziel: kleine Hashtafel, wenig Kollisionen
8.1
Hashing mit Verkettung (Chaining)
Die i-te Liste in Tafel T (0 ≤ i ≤ m − 1) enthält alle x ∈ S mit h(x) = i
0
1
2
→ 2 → 21
Laufzeit: worst-case: O(n) (alle Elemente in einer Liste), aber im Mittel viel besser.
Wahrscheinlichkeitsannahmen:
1. h(x) kann in O(1) ausgewertet werden
|
2. h−1 (i) = |U
m für alle i = 0, . . . , m − 1 (gleichmäßige Verteilung der Zahl der Einträge)
h soll Einträge von U gleichmäßig verteilen
3. Für eine Folge von n Operationen gilt: Wahrscheinlichkeit, dass j-tes Element der Folge ein festes
x ∈ U ist, ist N1 .
⇒ Operationen sind unabhängig und gleichverteilt.
⇒ Sei xk Argument der k-ten Operation
1
prob(h(xk ) = i) = m
d.h. auch Funktionswerte sind gleichverteilt.
85
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
8
HASHING
Definition:
(
1 , falls x 6= y, h(x) = h(y)
δh (x, y) =
0 , sonst
X
δh (x, S) =
δh (x, y) (Zahl der Element in T (h(x)))
y∈S
⇒ Kosten von Operation Zugrif f (x) = 1 + δh (x, S)
Satz: Mittlere Kosten von Zugrif f (x) sind 1 +
n
m
= 1 + β (β . . . Belegungsfaktor)
Beweis:
Sei h(x) = i und pik die Wahrscheinlichkeit, dass Liste i genau k Elemente enthält, dann ist
n
1 n−k
1 k
· 1− m
. Erwartungswert der Kosten des Zugrif f (x) ist:
pik =
· m
k
n−k
X n 1 k X
X
1
· 1−
k·
·
pik (1 + k) =
pik +
k
m
m
| {z }
k≥0
=1
Da k ·
n
k
=n·
n−1
k−1
, gilt
=
=
k−1 n−k
n X n−1
1
1
· 1−
·
·
k−1
m
m
m
n−1
n
1
1
n
1+
·
+ 1−
=1+
m
m
m
m
1+
Wie groß sollte β sein?
β ≤ 1: Zugriff erwartet in O(1)
β ≤ 41 : Platz für Hashtafel und Listen ist O(n + m) = O(n + nβ )
≈ O(n) für geeignet große β, z.B. β =
1
2
Beachte: Durch Einfügen und Streichen kann β schnell zu groß bzw. zu klein werden. ⇒ Rehashing.
⇒ Folge von Hashtafeln T0 , T1 , . . . der Größe m, 2m, 4m, . . . (Ti hat die Größe 2i · m)
⇒ Falls β = 1: Umspeichern in Ti+1 ⇒ β =
1
2
⇒ Falls β = 14 : Umspeichern nach Ti−1 ⇒ β =
1
2
Technik: Amortisierte Analyse zeigt, dass n Operationen erwartet in O(n) gehen.
Alternative: Offene Adressierung. Nur 1 Element pro Tafeleintrag. Folge von Hashfunktionen. Ist 1.
Eintrag belegt, probiere zweiten.
h1 , h2 , . . . z.B. hi (x) = (h(x) + 1) mod m (linear probing) oder hi (x) = h(x) + c1 · i + c2 · i2 mod m
(quadratic probing)
8.2
Perfektes Hashing
Die Hashfunktion soll injektiv sein. Sei S bekannt.
Stufe 1: Hashing mit Verkettung ⇒ Listen
Stufe 2: Für jede Liste eine eigene injektive Hashfunktion.
86
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
8
HASHING
Wahl einer injektiven Hashfunktion: Sei U = {0, . . . , N − 1}, hk : {0, . . . , N − 1} → {0, . . . , m − 1},
k ∈ {1, . . . , N − 1} mit hk (x) = ((k · x) mod N ) mod m.
Sei S bekannt. Wähle k mit hk injektiv. Wir messen Injektivität wie folgt:
bik = |{x ∈ S|hk (x) = i}| für 1 ≤ k ≤ N − 1, 0 < i ≤ m − 1
also bestimmen wir die Zahl der x ∈ S mit gleichem Hashwert i für hk . Dann ist
bik (bik − 1) = (x, y) ∈ S 2 |x 6= y, hk (x) = hk (y) = i , also die Zahl der Paare, die Injektivität verletzen.
Pm−1
Sei Bk = i=0 bik (bik − 1). Falls Bk < 2, dann ist hk |S injektiv.
Pm−1 n n
für alle i = 0, . . . , m − 1, dann gilt: Bk = i=0 m
·
Ist bik = m
n
m
−1 −n·
n
m
−1
Lemma: Mit obigen Vorraussetzungen und einer Primzahl N gilt:
N
−1 m−1
X
X
bik · (bik − 1) ≤ 2 ·
k=1 i=0
n(n − 1)
· (N − 1)
m
Beweis: siehe Literatur.
Bemerkung: Die mittlere Zahl der Kollisionen ist 2 · n(n−1)
.
m
⇒ Bei m > n(n − 1) ist die mittlere Anzahl von Kollisionen < 2.
⇒ Es existieren hk , hk|s injektiv.
Korollar: Mit obiger Voraussetzung gilt:
1. Es existiert ein k ∈ [1, . . . , N − 1], so dass Bk ≤ 2 ·
o
n
und |A| > N 2−1 .
2. Sei A = k|Bk > 4 · n(n−1)
m
⇒
P
k≥1
Bk ≥
P
⇒ Mindestens
k∈A
N −1
2
Bk >
N −1
2
·
4(n−1)n
m
hk haben Bk ≤
=2·
4n(n−1)
m
(n−1)n
m
n(n−1)
.
m
(N − 1)
Widerspruch!
Korollar: Mit obigen Voraussetzungen gilt:
1. Ein k ∈ [1, . . . , N − 1] mit Bk ≤2 ·
n(n−1)
m
kann in Zeit O(m + N n) bestimmt werden.
2. Sei m = n(n − 1) + 1, dann gibt es ein k mit hk|S injektiv und k kann in Zeit O(n2 + nN ) gefunden
werden.
3. Sei m = 2n(n − 1) + 1, dann ist die Hälfte der hk|S injektiv. Besimmungszeit ist ransomisiert O(n2 ).
4. Ein k ∈ [1, . . . , N − 1] mit Bk ≤ 4 ·
n(n−1)
m
kann randomisiert in Zeit O(m + n) gefunden werden.
5. Sei m = n. Ein k mit Bk ≤ 2(n − 1) kann in Zeit O(nN ) gefunden werden.
6. Sei m = n. Randomisiert kann ein k mit Bk ≤ 4 · (n − 1) in O(n) gefunden werden.
87
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
8
HASHING
Realisierung:
√
1. Bei m = n gibt es ein hk , so dass die Länge der Listen O( n), da Bk maximal das Quadrat der
Längen und Bk < 4n ist.
2. Wende auf jede Teilmenge mehrmals Hashing an. Sei |S| = n = m.
(a) Sei k gewählt, so dass Bk ≤ 4(n − 1) < 4n.
(b) Sei wi = {x ∈ S|hk (x) = i}, bi = |wi | und mi = 2 · bi · (bi − 1) + 1. Wähle ki mit hki (x) =
(ki x mod N ) mod m.
hki ist injektiv für wi
P
3. Sei si = j<i mj . Speichere x in T (si +j) wobei i = (kx mod N ) mod m und j = (ki x mod N ) mod mi .
Platz: m =
Pn−1
i=0
mi =
Pn−1
i=0
2 · bi (bi − 1) + 1 = n + 2 · Bk ≤ 9n = O(n)
Laufzeit:
1. O(n)
P
2. & 3. O ( |wi |) = O(n)
Satz: Mit obigen Voraussetzungen kann für S eine perfekte Hashfunktion mit O(1) Zugriffszeit und
Tafel der Größe O(n) in Zeit O(nN ) deterministisch und in O(n) randomisiert gefunden werden.
Es gibt auch die dynamische Version, bei der S nach nud nach aufgebaut wird. Dies geht in Zeit O(n) bei
einer Tafel der Größe O(n).
n
Beim Hashing mit Verkettung
wird
eine Listenlänge von 1 + m = 1+β erwartet, aber die erwartete Länge
der längsten Liste ist O
log n
log log n
.
88
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
9
MATCHING IM DATING-BUSINESS
1
Beweis: Sei S zufällig aus U gewählt, prob(h(x) = i) = m
für x ∈ S, i ∈ [0, . . . , m − 1], L die Länge der
längsten Liste und l(i) die Länge der Liste i.
j
1
n
prob(l(i) ≥ j) ≤
m
m
Es gilt:
m−1
X
prob(max l(i) ≥ j) ≤
i
prob(l(i) ≥ j)
i=0
1
m
j
n!
= m·
(n − j)! · j!
n j−1 1
≤ n·
·
m
j!
≤ m·
E(L)
=
X
n
j
1
m
j
prob(max l(i) ≥ j)
j≥1
≤
X
j≥1
n
Sei j0 = min j|n
n j−1
m
·
1
j!
n j−1 1 ·
min 1, n ·
m
j!
o
≤ 1 ≤ min {j|n ≤ j!}, da
j
Es gilt j! ≥ 2j 2 , also gilt: j0 = O logloglogn n
⇒ E(L) ≤
j0
X
n
m
≤ 1.
1+
j=1
= O
X
1
j−j0
j>j0 j0
log n
log log n
Beachte: Im Mittel sind Längen O(1 + β). Es gibt Listen mit Länge O
log n
log log n
.
Z UR V ORLESUNG VOM 17.07.2007 GIBT ES EINE P RÄSENTATION, DIE AUF DER V ORLESUNGSHOMEPA GE ZU FINDEN IST. I M F OLGENDEN DAHER NUR DER ZUGEHÖRIGE T AFELANSCHRIEB.
9
Matching im Dating-Business
Formalisierung
Eingabe: Rangordnung von einer Person zu allen anderen (weiblich/männlich)
Formal: Zwei Mengen A = {1, . . . , n} und B = {1, . . . , n}
Rangordnung:
∀ a ∈ A ∃ Ra : B → {1, 2, . . . , n}, Ra ist bijektiv
∀ b ∈ B ∃ Rb : A → {1, 2, . . . , n}, Rb ist bijektiv
Ausgabe: Gesucht sind n Dupel.
Bijektive Zuordnung M : A → B suchen (Matching), so dass M stabil ist.
89
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
9
MATCHING IM DATING-BUSINESS
Was ist Stabilität? ∀ a ∈ A und (a, M (a))
| {z }
=b
• ∀ a 6= a ∈ A : Ra0 (b) > Ra0 (M (a0 )) und Rb (a) > Rb (a0 )
| {z }
=b0
• ∀ b0 6= b ∈ B : Rb0 (a) > Rb0 (a0 ) und Ra (b) > Ra (b0 )
Beweis zu Satz 9.1:
Sei M das vom Algorithmus berechnete Matching.
Widerspruch: Angenommen ∃ (m, w) ∈ M , (m0 , w0 ) ∈ M , so dass
• Rw (m0 ) > Rw (m) und Rm0 (w) > Rm0 (w0 ) oder
• Rw0 (m) > Rw0 (m0 ) und Rm (w0 ) > Rm (w)
Beweis zu stabilen Matchings:
S 6= S ? , so dass m nicht mit der besten für ihn erreichbaren Frau w an einem Tisch sitzt.
⇒ w präferiert m0
Wenn m der erste Mann im Algorithmus ist, dem das passiert, ist m0 bisher nicht abgelehnt worden.
⇒ m0 findet w attraktiver als alle anderen w0 6= w
Da w für m erreichbar ist, muss es S 0 geben mit (m, w) ∈ S 0 .
Sei w0 die Frau, mit der m0 zusammensitzt. ⇒ Widerspruch!
90
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
INHALTSVERZEICHNIS
Inhaltsverzeichnis
1 Worum geht es?
2
2 Was ist ein Algorithmus?
2
3 Analyse von Algorithmen
2
3.1 Allgemeine Komplexität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
3.2 Asymptotische Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3.3 O-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3.4 O-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3.5 Ω-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3.6 ω-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3.7 Θ-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4 Suchen
4
4.1 Lineare Suche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
4.2 Binäre Suche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
4.3 Interpolationssuche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
5 Sortieren
13
5.1 Sortieren durch Einfügen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.2 QuickSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.3 MergeSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.4 HeapSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.5 BucketSort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
5.6 Auswahlproblem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
6 Balancierte Bäume
21
6.1 Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
6.2 AVL-Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
6.3 B-Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.4 Kantenmarkierte Suchbäume (“Tries”) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.5 PATRICIA-Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
6.6 Randomisierte Suchbäume: Skiplists (W. Pugh) . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
7 Graphenalgorithmen
31
7.1 Darstellung von Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
7.2 Topologisches Sortieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
7.3 Durchmusterungsalgorithmen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
7.3.1 Tiefensuche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
7.3.2 Starke Zusammenhangskomponenten (SZKs) . . . . . . . . . . . . . . . . . . . . . . . . 38
91
www.bioinfoblog.de
Algorithmen, SS 2007 (Nina Zweig, Prof. Kaufmann)
8 Hashing
INHALTSVERZEICHNIS
85
8.1 Hashing mit Verkettung (Chaining) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
8.2 Perfektes Hashing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
9 Matching im Dating-Business
89
92
www.bioinfoblog.de
Herunterladen