Beispiel

Werbung
Gliederung
5. Compiler
1.
2.
3.
4.
Struktur eines Compilers
Syntaxanalyse durch rekursiven Abstieg
Ausnahmebehandlung
Arrays und Strings
6. Sortieren und Suchen
1. Grundlegende Datenstrukturen
2. Bäume
3. Hash-Verfahren (Streuspeicherung)
7. Graphen
1. Darstellung und Topologisches Sortieren
2. Kürzeste Wege
3. Fluß- und Zuordnungsprobleme
Traversieren von Graphen (1)
• Viele Algorithmen auf Graphen beruhen darauf, daß man alle
Knoten (oder alle Kanten) des Graphen durchwandert:
den Graphen traversiert.
• Solche Traversierungen können ähnlich definiert werden, wie
die entsprechenden Baumwanderungen.
• Allerdings muss man bei Graphen darauf achten, dass man
nicht in Endlosschleifen gerät, wenn der Graph Zyklen hat.
• Aus diesem Grund markiert man bereits besuchte Knoten.
• Dies ist eine Technik, die aus der Suche nach dem Ausweg
aus einem Labyrinth bekannt ist (Tom Sawyer).
• Ariadne benutzte ein Garnknäuel, um Theseus die Rückkehr
aus dem Labyrinth zu ermöglichen, in dem er den Minotaurus
getötet hatte.
Traversieren von Graphen (2)
Für die Traversierung betrachten wir die folgenden Strategien:
Tiefendurchlauf (depth first)
Breitendurchlauf (breadth first)
• Der Tiefendurchlauf entspricht der PreorderBaumtraversierung, der Breitendurchlauf der LevelorderBaumtraversierung.
• Alle folgenden Algorithmen können sowohl auf gerichtete als
auch auf ungerichtete Graphen angewendet werden.
• Bei Traversierungsalgorithmen ist es nicht sinnvoll,
unzusammenhängende Graphen zu untersuchen.
• Bei den folgenden Überlegungen setzen wir daher generell
zusammenhängende Graphen voraus.
Tiefendurchlauf (1)
• Der Tiefendurchlauf lässt sich sehr einfach implementieren:
Wir betrachten eine rekursive Implementierung.
Damit werden die noch zu besuchenden Knoten im Keller
verwaltet.
• Der folgende Algorithmus Depth-First-Visit besucht alle
Knoten, die von einem Ausgangsknoten k aus erreichbar sind,
und markiert jeweils die besuchten Knoten.
void Depth-First-Visit (int k ){
if (k ist noch nicht markiert){
Markiere (k);
Besuche alle Nachbarn von k mit Depth-First-Visit;
}
}
Tiefendurchlauf (2)
• Wir benutzen ein statisches Feld für die Markierungen:
private static boolean [] besucht;
• Zunächst benötigen wir eine Prozedur, die die eigentliche Tiefensuche
startet.
• Sie stellt ein Array für die Markierungen zur Verfügung. Die rekursive
Tiefensuche beginnt:
void DFVisit(int k){
besucht = new boolean [KnotenZahl];
RekDFVisit(k);
}
Tiefendurchlauf (3)
• Die rekursive Prozedur rekDFVisit testet ob der Knoten k bereits markiert
ist.
• Falls das nicht der Fall ist, markiert sie den aktuellen Knoten und führt,
ähnlich wie bei den Baumwanderungen, eine Besuchermethode aus.
• Statt einer expliziten Besuchermethode haben wir allerdings nur eine
einfache Ausgabeanweisung eingebaut.
• Schließlich besucht rekDFVisit alle Nachbarn, zu denen es eine direkte
Verbindung gibt:
void rekDFVisit(int k){
int Max = KnotenZahl;
if ( !besucht[k] ){
besucht[k] = true;
System.out.println(Knoten[k]);
Iterator iter = getEdges (k);
while (iter.hasNext ()) {
Edge v = (Edge) iter.next ();
rekDFVisit(v.dest);
}
}}
Tiefendurchlauf – Beispiel - 1
• Angewandt auf Beispiel 1 ergibt sich:
Graph Graph1 = new Graph();
Graph1.DFVisit(0);
Graph1.DFVisit(2);
Graph1.DFVisit(7);
Marburg
Gießen
Frankfurt
Bonn
Köln
Mannheim
Fulda
Kassel
Würzburg
Fulda
Frankfurt
Bonn
Köln
Gießen
Marburg
Kassel
Mannheim
Würzburg
Bonn
Frankfurt
Fulda
Gießen
Köln
Marburg
Kassel
Würzburg
Mannheim
Tiefendurchlauf – Beispiel - 2
• Angewandt auf Beispiel 2 ergibt sich:
Graph2.DFVisit(0);
San Francisco
San Rafael
Richmond
Oakland
Hayward
San Mateo
Palo Alto
Fremont
San Jose
Santa Clara
Scotts Valley
Santa Cruz
Watsonville
Half Moon Bay
Pacifica
Graph2.DFVisit(4);
San Mateo
San Francisco
San Rafael
Richmond
Oakland
Hayward
Fremont
Palo Alto
Santa Clara
San Jose
Watsonville
Santa Cruz
Scotts Valley
Half Moon Bay
Pacifica
Graph2.DFVisit(9);
Santa Clara
Palo Alto
San Mateo
San Francisco
San Rafael
Richmond
Oakland
Hayward
Fremont
San Jose
Watsonville
Santa Cruz
Scotts Valley
Half Moon Bay
Pacifica
Breitendurchlauf (1)
• Ähnlich wie bei der Baum-Traversierung in Level-Order wird
eine Warteschlange als Hilfsspeicher verwendet.
void BFVisit(int k){
int Max = KnotenZahl;
boolean [] besucht = new boolean [Max];
Queue q = new Queue(Max+5);
try {
q.enQueue(k);
while(!q.istLeer()){
int l = q.deQueue();
if (!besucht[l] ){
besucht[l]= true;
System.out.println(Knoten[l]);
Iterator iter = getEdges (k);
while (iter.hasNext ()) {
Edge v = (Edge) iter.next();
q.enQueue(v.dest);
}
}}} // try while und if beendet
catch(QueueFehler s){ System.out.println(
"Fehler bei der Breitensuche: "+s);
}}
Breitendurchlauf– Beispiel - 1
• Angewandt auf Beispiel 1 ergibt sich:
Graph Graph1 = new Graph();
Graph1.BFVisit(0);
Graph1.BFVisit(2);
Graph1.BFVisit(7);
Marburg
Gießen
Kassel
Frankfurt
Fulda
Köln
Bonn
Mannheim
Würzburg
Fulda
Frankfurt
Gießen
Kassel
Würzburg
Bonn
Mannheim
Köln
Marburg
Bonn
Frankfurt
Köln
Mannheim
Fulda
Gießen
Würzburg
Kassel
Marburg
Breitendurchlauf– Beispiel - 2
• Angewandt auf Beispiel 2 ergibt sich:
Graph2.BFVisit(0);
San Francisco
San Rafael
Oakland
San Mateo
Pacifica
Richmond
Hayward
Palo Alto
Half Moon Bay
Fremont
Santa Clara
Santa Cruz
San Jose
Scotts Valley
Watsonville
Graph2.BFVisit(4);
San Mateo
San Francisco
Hayward
Palo Alto
Half Moon Bay
San Rafael
Oakland
Pacifica
Fremont
Santa Clara
Santa Cruz
Richmond
San Jose
Scotts Valley
Watsonville
Graph2.BFVisit(9);
Santa Clara
Palo Alto
San Jose
Scotts Valley
San Mateo
Fremont
Watsonville
Santa Cruz
San Francisco
Hayward
Half Moon Bay
San Rafael
Oakland
Pacifica
Richmond
Transitive Hülle
Eine zweistellige Relation R auf einer Menge V heißt transitiv, falls gilt :
∀ x, y, z ∈V : (x,y) ∈ R und (y,z) ∈ R → (x,z) ∈ R.
Die transitive Hülle t(R) einer zweistelligen Relation R auf V ist die kleinste
Relation Q, für die gilt: Q ist transitiv und R ⊆ Q.
• Fasst man R als Graphen auf V auf, so gibt es einen Weg von x nach y
genau dann, wenn es in t(R) eine Kante von x nach y gibt.
• Man kann die Antwort auf die Frage „Gibt es in R einen Weg von x
nach y?“ direkt aus der transitiven Hülle ablesen.
• Es bleibt dann noch die Frage, wie man t(R) zu gegebenem R
ermitteln kann.
Transitive Hülle: Beispiel
A
D
A
D
F
F
B
B
H
C
E
Ausgangsgraph G
G
H
C
E
transitive Hülle t(G)
G
Warshall's Algorithmus
• Warshalls Algorithmus berechnet die transitive Hülle einer
Relation, die durch eine Adjazenzmatrix
boolean [][] A = { ... };
int dim = A.length;
dargestellt ist.
• A wird dabei schrittweise zur transitiven Hülle vergrößert:
void WarshallAlg(){
int Max = dim;
for (int y = 0; y < Max; y++)
for (int x = 0; x < Max; x++)
if (A[x][y]) for (int z = 0; z < Max; z++)
if (A[y][z]) A[x][z] = true;
}
Frage: Funktioniert dieser Algorithmus auch, wenn man
die x- und die y- Schleife vertauscht ???
Anmerkungen zu Warshall's Algorithmus
• Wichtig ist bei Warshall's Algorithmus die Reihenfolge der
Schleifen. Es spielen jeweils die Paare A[x,y] und A[y,z] eine
Rolle. Von Bedeutung ist, dass die äußere Schleife über das
mittlere Element verläuft.
• Man erkennt unmittelbar, dass Warshalls Algorithmus nichts
Falsches tut, da er A[x,z] nur dann auf true setzt, wenn
bereits A[x,y] und A[y,z] true sind.
• Dass er auch tatsächlich alle notwendigen Verbindungen
hinzufügt, kann man durch Induktion über die äußere
Schleife beweisen.
Warshall: Beispiel 1
A
B
A
B
D
C
D
C
• Bei diesem Beispiel ist die Reihenfolge der Darstellung in der
Matrix wichtig
Ausgangsgraph G
A
B
C
D
A
0
0
0
0
B
1
0
0
0
C
0
1
0
0
D
0
0
1
0
transitive Hülle t(G)
A
B
C
D
A
0
0
0
0
B
1
0
0
0
C
1
1
0
0
D
1
1
1
0
X-Y-Pseudo-Hülle
A
B
C
D
A
0
0
0
0
B
1
0
0
0
C
1
1
0
0
D
1
1
1
0
Warshall: Beispiel 2
A
D
A
D
B
C
E
Ausgangsgraph G
A
B
C
D
E
A
0
0
1
1
0
B
B
1
0
0
0
0
C
0
1
0
0
0
D
1
0
0
0
0
E
1
1
0
0
0
C
E
transitive Hülle t(G)
A
B
C
D
E
A
1
1
1
1
0
B
1
1
1
1
0
C
1
1
1
1
0
D
1
1
1
1
0
E
1
1
1
1
0
X-Y-Pseudo-Hülle
A
B
C
D
E
A
1
1
1
1
0
B
1
0
1
1
0
C
1
1
1
1
0
D
1
0
1
1
0
E
1
1
1
1
0
Korrektheit von Warshall's Algorithmus (1)
• Dass Warshall's Algorithmus tatsächlich alle notwendigen
Verbindungen hinzufügt, kann man durch Induktion über die
äußere Schleife beweisen.
• Als Induktionshypothese dient folgende Aussage P zu
gegebenem y:
• P(y) ≡ Gibt es zu beliebigen Knoten u und v einen Weg von u
nach v, so dass alle Zwischenknoten aus der Menge
M = {0, ...,y} sind, so wird in der y-ten Iteration
A[u,v] = true gesetzt.
Korrektheit von Warshall's Algorithmus (2)
(1)
y = 0 M = {0}
Gibt es einen Pfad von u nach v mit allen Zwischenknoten in {0}, dann
sind offensichtlich (u,0) und (v,0) in der Relation R enthalten!
Innerhalb der Schleife wird dann das Tripel (x,y,z) mit x=u, y=0 und
z=v im 0-ten Durchlauf bearbeitet und es wird (u,v) true gesetzt.
(2) Die Behauptung P(y) gelte für 0 ... y.
Es sei nun ein Weg von u nach v vorhanden, der y+1 benutzt. Dann
gibt es einen der y+1 nur einmal benutzt. Auf Grund der
Induktionshypothese wurde in einer früheren Iteration der Schleife
bereits (u,y+1) und (y+1,v) eingefügt. In der (y+1)-ten Iteration wird
daher (u,v) eingefügt. Also gilt auch P(y+1).
u
y+1
v
Wenn P(y) für alle y gilt, was wir bewiesen haben, folgt daraus, dass
der Algorithmus tatsächlich alle notwendigen Kanten einfügt!
Wege in bewerteten Graphen
• In einem bewerteten Graphen hatten wir bereits zu einem
gegebenen Weg zwischen zwei Knoten u und v die Länge
des Weges definiert:
W = (u=k0 , k1, ..., kp=v)
L(W) = Kantenwert(k0,k1) + ... + Kantenwert(kp-1,kp)
• Für die Definition einer Entfernung ist diese Definition
jedoch unbefriedigend, da wir verschiedene Wege mit
gleichem Anfang und Ende haben können:
Im Beispiel1 gilt:
L(Marburg, Gießen, Frankfurt, Mannheim) = 184
und:
L(Marburg, Gießen, Köln, Bonn, Mannheim) = 462
• Eine Entfernung für zwei Knoten u und v in einem
bewerteten zusammenhängenden Graphen nehmen wir
daher das Minimum der Längen aller Wege.
Kürzeste Wege : Floyd
• In einem zusammenhängenden bewerteten Graphen
definieren wir die Entfernung dis(u,v) zwischen zwei Knoten
u und v als das Minimum der Menge
{ L(W) : W ist ein Weg von u nach v}
• Um die kürzeste Entfernung zwischen je zwei Knoten eines
Graphen zu finden (engl.: all pairs shortest path problem), kann
man Warshall's Algorithmus leicht verändern.
• Dieser Algorithmus wird gewöhnlich R.W. Floyd zugeschrieben.
• Anstelle der booleschen verwenden wir jetzt wieder eine
bewertete Adjazenzmatrix A und setzen dabei jeweils statt
A[x][z] = true
A[x][z] = min(A[x][z] , A[x][y] + A[y][z] )
Die Komplexität von Floyd's Algorithmus ist: O (N3)
Kürzeste Wege : alternativ
• Floyds Algorithmus berechnet alle kürzesten Entfernungen in
einem gegebenen Graphen.
• Da man sich aber gewöhnlich nur für eine bestimmte kürzeste
Entfernung interessiert (und nicht für alle), wollen wir hier
einen Algorithmus diskutieren, der auf einer ähnlichen Idee
aufbaut wie Warshalls Algorithmus, der aber den Vorteil hat,
zu terminieren, sobald die kürzeste Entfernung zwischen zwei
bestimmten Knoten gefunden wurde.
• Dieser Algorithmus stammt von E.W.Dijkstra (1959).
• Er berechnet für einen vorgegebenen Knoten u die kürzeste
Entfernung zu allen anderen Knoten (engl.: single source
shortest path problem).
Dijkstra’s Algorithmus (1)
Wir suchen die kürzeste Entfernung von einem Knoten u zu einem Knoten v.
Grundidee des Algorithmus:
• Dijkstra's Algorithmus färbt einen Graphen G schrittweise grün ein.
• Ausgehend von der Menge S1 = {u} betrachten wir eine immer grösser
werdende Menge der S1 "grünen Knoten". Für jeden Knoten k dieser Menge
ist die kürzeste Entfernung von u nach k bekannt.
• Die Menge der Knoten, die nicht in S1 sind, für die es aber eine direkte
Verbindung, also eine Kante zu einem Knoten aus S1 gibt, nennen wir S2 :
die "gelben Knoten".
• Die Menge der restlichen Knoten des Graphen nennen wir S3 : die "roten
Knoten".
• Wir, beginnen mit S1 = {u} und S2 : Menge der Nachbarn von u.
• In einem Erweiterungsschritt erweitern wir S1 um einen Knoten k aus S2 ,
entfernen k aus S2 und nehmen alle (neuen) Nachbarn von k zu S2 hinzu.
Dijkstra’s Algorithmus (2)
• Wir benutzen dabei folgende Definition der Nachbarn einer Menge S von
Knoten: N(S) = {n | n ist mit mindestens einem s ∈ S direkt verbunden,
aber nicht in S enthalten}
S3
S2
S1
u
G = S1 ∪ S 2 ∪ S 3
• Wir vergrößern die Menge der grünen Knoten um jeweils einen Knoten.
• Wenn der Graph G aus n Knoten besteht, haben wir also spätestens nach n
Schritten die kürzeste Entfernung von u nach v gefunden.
• Leider ist in Dijkstra's Algorithmus die Auswahl des nächsten Knotens der
grün wird nicht zielgerichtet, daher hoffen wir dass der Algorithmus früher
terminiert – wieviel früher wissen wir aber nicht.
Dijkstra’s Algorithmus (3)
Beginn des Algorithmus:
• Wir beginnen mit S1 = {u} und S2 = N(S1) .
• Erweiterungsschritt:
• Wir betrachten alle Paare (k1, k2) mit k1∈ S1 und k2∈ S2
• Zur Erweiterung wählen wir k = k2 aus einem Paar (k1, k2) für das der
Ausdruck dis(u, k1) + Kantenwert(k1, k2) ein Minimum annimmt.
• Dieser Wert ist die kürzeste Entfernung dis (u, k) !
(Dies wird auf der nächsten Folie noch bewiesen).
• Wir können nunmehr S1 = S1 ∪ {k} und S2 = N(S2 - {k} ) nehmen.
• Dijkstra's (Original-) Version des Algorithmus hat einen Aufwand von O(N2)
im durchschnittlichen Fall.
Dijkstra’s Algorithmus (4)
• Wir wollen uns noch vergewissern, dass mit Hilfe der obigen Konstruktion
auch tatsächlich der kürzeste Weg von u nach v gefunden wurde.
Beweis:
• Angenommen, es gäbe einen kürzeren Weg von u nach v, dann sei k3 der
letzte Zwischenknoten dieses Weges, der noch aus S1 ist, und k4 sei sein
Nachfolger. Also hat der Weg die Struktur u....k3k4.....v.
S2
k4
k3
S1
u
k1
k2
• Da der Gesamtweg nach k2 angeblich kürzer ist, ist auch der Weg von u
nach k4 kürzer als der bisher gefundene Weg uK2
• Da aber die sonstigen Voraussetzungen der Konstruktion des Weges erfüllt
sind, wäre das Paar (k3, k4) anstatt des Paares (k1, k2) von dem
Algorithmus ausgewählt worden, womit wir einen Widerspruch
herbeigeführt haben. K3 muss in liegen!
Beispiel 1
Der kürzeste Weg von Bonn nach Kassel
S1
{0}
(1) {0}
(2) {0, 5}
(3) {0, 1, 5}
(4) {0, 1, 3, 5}
(5) {0, 1, 3, 5, 6}
(6) {0, 1, 3, 5, 6, 7}
(7) {0, 1, 2, 3, 5, 6, 7}
(8) {0, 1, 2, 3, 5, 6, 7, 8}
minimale Entfernung
{0, 0, 0, 0, 0, 0, 0, 0, 0}
{0, 0, 0, 0, 0, 0, 0, 0, 0}
{0, 0, 0, 0, 0, 34, 0, 0, 0}
{0,181, 0, 0, 0, 34, 0, 0, 0}
{0,181, 0, 208, 0, 34, 0, 0, 0}
{0,181, 0, 208, 0, 34, 224, 0, 0}
{0,181, 0, 208, 0, 34, 224, 238, 0}
{0,181, 285, 208, 0, 34, 224, 238, 0}
{0,181, 285, 208, 0, 34, 224, 238, 317}
k1 k2 min
0
0
5
0
3
1
1
7
0
5
1
3
6
7
2
8
4
0
34
181
208
224
238
285
317
342
Beispiel 2 (1)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (2)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (3)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (4)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (5)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (6)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (7)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (8)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (9)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (10)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (11)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (12)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (13)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (14)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Beispiel 2 (15)
San Rafael
1
15
Richmond
2
18
San Francisco
15
12
0
3
Oakland
20
15
20
Pacifica 14
5 Hayward
San Mateo
15
Half Moon Bay
Auf dem Wege
von San Rafael
nach Scotts Valley
25
13
20
4
14
18
6
10
10
10
12
20
15
Palo Alto
50
7 Fremont
15
9
8 San Jose
Santa Clara
35
Scotts Valley
Santa Cruz
70
60
Watsonville
11
Kürzeste Wege als Programm (1)
• Wir vereinfachen den Algorithmus wie folgt:
• Wir nehmen als Menge S2 stets die ganze Restmenge S3.
• Dadurch steigt der Aufwand zwar wieder auf O(N3) , aber das
Programm wird einfacher.
void minSuche(int u, int v){
int Max = KnotenZahl;
boolean [] S = new boolean[Max];
S[u] = true;
int [] MinEntf = new int [Max];
...
Kürzeste Wege als Programm (2)
...
while (!S[v]){
int MinMin = 1000000;
int minind = 0;
for (int k1 = 0; k1 < Max; k1++)
for (int k2 = 0; k2 < Max; k2++)
if (S[k1] && !S[k2] && (Kanten[k1][k2] > 0)){
int MinNeu = Kanten[k1][k2] + MinEntf[k1];
if (MinNeu < MinMin){
MinMin = MinNeu;
minind = k2;
}
}
S[minind] = true;
MinEntf[minind] = MinMin;
System.out.println("nach "+ Knoten[minind] +
" ist " + MinMin + " km.");
}
}
Kürzeste Wege – Beispiel - 2
Min-Suche Ausgangsknoten: San Rafael
Zielknoten: Scotts Valley
nach Richmond ist 15 km.
nach San Francisco ist 18 km.
nach Oakland ist 30 km.
nach Pacifica ist 33 km.
nach San Mateo ist 38 km.
nach Half Moon Bay ist 48 km.
nach Hayward ist 50 km.
nach Palo Alto ist 56 km.
nach Fremont ist 64 km.
nach Santa Clara ist 66 km.
nach San Jose ist 81 km.
nach Santa Cruz ist 98 km.
nach Scotts Valley ist 101 km.
Kürzester Weg und aufspannender Baum
• Ist v der letzte (d.h. von u am weitesten entfernte) Knoten
des Graphen G, wie im folgenden Beispiel, so liefert
Dijkstra's Algorithmus offenbar einen aufspannenden Baum
für G - und zwar gerade denjenigen, der für jeden Knoten k
den kürzesten Weg von u nach k darstellt.
• Beispiel 1
Min-Suche Ausgangsknoten: Bonn
Zielknoten: Kassel
nach Köln ist 34 km.
nach Frankfurt ist 181 km.
nach Gießen ist 208 km.
nach Mannheim ist 224 km.
nach Marburg ist 238 km.
nach Fulda ist 285 km.
nach Würzburg ist 317 km.
nach Kassel ist 342 km.
Kürzester Weg und aufspannender Baum:
Beispiel 1
Köln 5
174
Marburg
Bonn
224
106
3
Gießen
66
181
1
88
6
Mannheim
4 Kassel
96
7
30
34
0
104
2 Fulda
104
Frankfurt
136
93
8 Würzburg
Literatur
• Die Vorlesungsfolien wurden aus der Vorlesung „Informatik
II a, SS 2002“ von Prof. Sommer (Uni-Marburg)
übernommen
Herunterladen