Powerpoint-Präsentation

Werbung
Kürzeste Wege
Implementierung des Algorithmus von Dijkstra
Helmut Paulus
Speyer, 3.-5.11.08
Teil 1
Objektorientierte Modellierung von Graphen
Graphen
3
Ein Graph beschreibt eine Struktur aus
Objekten und den Beziehungen
zwischen ihnen.
Ein Graph besteht aus
– einer Menge von Knoten (Objekten) und
– einer Menge von Kanten (Beziehungen),
die die Knoten verbinden.
Klassische Probleme

Eulersche Wanderungen

Hamiltonsche Rundreisen

Labyrinthproblem

Problem des Handlungsreisenden

Kürzeste Wege
4
Algorithmus von Dijkstra
{Eingabe: Graph G; Startknoten s des Graphen}
für alle Knoten w
setze dg(w) = ∞
setze dg(s) = 0
füge s in eine (zunächst leere) Datenstruktur D ein
solange D nicht leer ist
entnimm einen Knoten w mit minimalem dg(w) aus D
für alle Kanten {w,u}
falls dg(u) = ∞
füge u in D ein
falls dg(u) > dg(w) + g({w,u})
setze dg(u) = dg(w)+g({w,u})
{Ausgabe: gewichteter Abstand dg(w) aller Knoten w vom Startknoten s}
Quelle: http://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm
5
Algorithmus von Dijkstra
Abgewandelte Version:
{Eingabe: Graph G; Startknoten s, Zielknoten z des Graphen}
für alle Knoten w
setze Entfernung(w) = 0
füge s in eine (zunächst leere) Warteschlange WS ein
solange erstesElement von WS <> z
entnimm den ersten Knoten w von WS
für alle Kanten {w,u}
falls u noch nicht besucht
falls Entfernung(u) = 0
setze Vorgänger von u auf w
füge u in WS ein
setze Entfernung(u) = Entfernung(w) + gewicht({w,u})
sonst
falls Entfernung(u) > Entfernung(w) + gewicht({w,u})
setze Vorgänger von u auf w
setze Entfernung(u) = Entfernung(w) + gewicht({w,u})
füge u erneut in WS ein
{Ausgabe: Abstand des Zielknotens z vom Startknoten s}
w expandieren
WS: Prioritätenwarteschlange, d. h. die Knoten werden nach ihrer Entfernung (Priorität) geordnet
einsortiert! Der Knoten mit kleinsten Entfernung steht am Anfang.
Algorithmus von Dijkstra
6
22
A
F
10
Gesucht:
16
12
25
B
6
Kürzester Weg von A nach E
E
5
C
12
D
6
WS: A/0
Algorithmus von Dijkstra
7
22
A
F
10
Gesucht:
16
12
25
B
6
Kürzester Weg von A nach E
E
5
C
12
D
6
WS:
Algorithmus von Dijkstra
8
0
22
22
A
F
10
10
12
25
B
6
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
12
D
6
WS: B/10, C/12, F/22
Algorithmus von Dijkstra
9
0
22
22
A
F
10
10
12
25
B
6
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
12
D
6
WS: C12, F22
Algorithmus von Dijkstra
10
0
22
22
A
F
10
10
12
35
25
B
6
12
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
D
6
15
WS: C/12, D/15, F/22, E/35
Algorithmus von Dijkstra
11
0
22
22
A
F
10
10
12
35
25
B
6
12
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
D
6
15
WS: D/15, F/22, E/35
Algorithmus von Dijkstra
12
0
22
22
A
F
10
10
12
35
25
B
6
12
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
D
6
15
WS: D/15, F/22, E/35
Algorithmus von Dijkstra
13
0
22
22
A
F
10
10
12
35
25
B
6
12
Kürzester Weg von A nach E
E
5
C
12
Gesucht:
16
D
6
15
WS: F/22, E/35
Algorithmus von Dijkstra
14
0
22
22
A
F
10
10
12
Gesucht:
16
6
21
25
B
E
5
C
12
Kürzester Weg von A nach E
D
12
6
WS: E/21, F/22
15
Nach Ausführung
0
22
A
10
10
12
25
E
5
C
12
16
B
6
Jeder besuchte Knoten enthält den
minimalen Abstand zum Startknoten,
sowie einen Verweis zu seinem
Vorgänger im Pfad (lineare Liste).
22
F
12
6
D
15
21
WS: F/22
15
Implementierung von Graphen
Objektorientierte Lösung:
TKnoten
Jeder Knoten ist ein Objekt
- name : string
Jede Kante ist ein Objekt
- kanten : Tkantenliste
- anzahlkanten : integer
TGraph
- anzahlKnoten : integer
- knoten : TKnotenliste
*
- initialisiere
+ create
- entfernung : integer
- nachfolger, vorgaenger : TKnoten
+ create(n : string; x,y : integer)
+ fuegeKantehinzu(nachbar :
Tknoten; e : integer)
1
+ berechneWeg(start, ziel : Tknoten)
+ gibAlleKnoten : Tknotenliste
+ gibKnoten(n : string)
+ gibAnzahlKnoten : integer
Das Graphobjekt verwaltet die Knoten und Kanten
und stellt den Suchalgorithmus zur Verfügung.
*
TKante
- gewicht : integer
- nachbar :TKnoten
+ create(k : TKnoten; e : integer)
+ gibGewicht : integer
+ gibNachbar : TKnoten
Zielsetzung
16
Ziel ist es, ein Programm zu entwickeln, mit dessen Hilfe man kürzeste
Wege im Graphen ermitteln kann. Folgende Anforderungen soll das
Programm erfüllen:
/1/ Der Graph wird als Bild auf der Benutzungsoberfläche angezeigt.
/2/ Man kann sich einen kürzesten Weg von einem eingegebenen Startzu einem eingegebenen Zielknoten berechnen und anzeigen lassen.
Arbeitsschritte:

Grafik mit Delphi

Entwicklung einer (Prioritäten-)Warteschlange

Implementierung des Graphen

Implementierung des Dijkstra-Algorithmus
Teil 2
Grafik mit Delphi
Zeichenfläche TCanvas
18
Canvas-Objekte dienen als Zeichenfläche für grafische Elemente.
Sie kapseln eine Vielzahl von Methoden zur Ausgabe von Grafik und Text in einem rechteckigen Bereich.
TCanvas
Brush : TBrush
Pen : TPen
Font : TFont
...
TCanvas-Werkzeuge Pen, Brush und Font,
zuständig für bestimmte Teilaufgaben:
Pinsel
Stift
– Füllfarbe, Muster ...
– Linienfarbe, Stil ...
Schriftart – Farbe, Schrifttyp ...
moveto(x,y : integer);
lineto(x, y : integer);
ellipse(x1,y1,x2,y2 : integer)
rectangle(x1,y1,x2,y2 : integer)
polygon(p : array of Tpoint);
TextOut(x, y: Integer; const Text: string);
...
Der Koordinatenursprung (0,0) ist in der
linken oberen Ecke einer Komponenten,
die ein Canvas-Objekt zur Verfügung
stellen.
Wie erhält man ein TCanvas-Objekt?
19
TCanvas-Objekte werden von einigen Delphi-Komponenten als Property zur Verfügung
gestellt: z. B.:
Formular, Paintbox, Image, Bitmap




Der Koordinatenursprung ist die linke obere Ecke der jeweiligen
Komponente.
Die positive y-Achse zeigt nach unten.
Die Image-Komponente speichert die Graphik zusätzlich in einer
Hintergrundbitmap, so dass das Bild automatisch anzeigt wird, wenn das
Formularfenster, nachdem es verdeckt war, wieder in den Vordergrund
geholt wird.
Formular und Paintbox zeichnen das Bild nur einmalig. Damit es nach
dem Verdecken wieder erscheint, muss das Zeichnen der Graphik in der
OnPaint-Ereignismethode der jeweiligen Komponente erfolgen. Dieses
Ereignis wird vom Betriebssystem automatisch ausgelöst.
20
Objekthierarchie
Das Bild-Objekt Bild vom Typ TImage mit Hilfe seines Attributs Canvas ein Leinwand-Objekt der
Klasse Tcanvas zur Verfügung. Dieses wiederum hat ein Zeichenstift-Objekt der Klasse TPen und
ein Malpinsel-Objekt der Klasse Tbrush.
Die entsprechenden Attribute Pen und Brush werden als Property zur Verfügung gestellt.
Beispiel: Blaues Rechteck
Bild.Canvas.Brush.Color := clbue;
Pinselfarbe blau
Bild.canvas.rectangle(10,10,100,20);
Rechteck mit der linken oberen Ecke am Punkt
(X1, Y1) und der rechten unteren Ecke am
Punkt (X2, Y2).
21
Aufgaben 1
1. Testen Sie das Beispielprogramm Grafiktest.exe
Variieren Sie verschiedene Modi der Pinsel und Stifte
Testen Sie insbesondere den NotXOR-Füllmodus
2. Entwickeln Sie ein Programm, das die Bilddatei Lageplan.jpg im Formular
anzeigt.
Teil 3
Entwicklung einer Warteschlange
Datentyp Schlange
23
Eine Schlange realisiert das Prinzip FIFO (First In First Out),
d. h. die Ausgabe erfolgt in gleicher Reihenfolge wie die Eingabe.
Spezialisierte Schlange:
Kopf
:Schlange
Kopf =
...
Hat
:Knoten
nachfolger =
kennt
name = A
:Knoten
nachfolger =
nil
name = B
Jedes Element kennt einen Nachfolger

Das Objekt Schlange dient der Verwaltung

Mit Hilfe seines Attributs Kopf hat es Zugriff auf das erste Element


Die Knoten implementieren das Einfügen nach dem FIFO-Prinzip,
neue Elemente werden vom Kopf an ans Ende gereicht
Der Nachfolger des letzten Elements zeigt immer auf nil; es ist die Stelle, wo neue
Elemente eingefügt werden.
Allgemeine Schlange
24
Schlange für beliebige Objekte
:Schlange
Kopf =
...
kennt
:Knoten
nachfolger =
inhalt =
:Object
kennt
:Knoten
nachfolger =
inhalt =
:Object
Jedes Element erhält ein Inhaltsobjekt
nil
Klassendiagramm
25
TSchlange
TKnoten
- inhalt : string;
- Kopf : TKnoten
+
+
+
+
+
+
create
istLeer: boolean
einfuegeKnotenein(k : Tknoten)
giberstesElement : TKnoten
entferneErstes
gibSchlangeAus(liste : TStrings)
hat
- nachfolger : TKnoten;
+ create (wert: string);
+ fuegeKnotenEin (nK: TKnoten)
+ gibKnotenAus (liste: TStrings);
+ setzeInhalt (wert: string);
+ setzeNachfolger (k: TKnoten);
+ gibInhalt : string;
+ gibNachfolger : TKnoten;
kennt
Klasse TSchlange
26
Operationen
• prüfen, ob die Schlange leer ist
• ein neues Element in die Warteschlange einfügen
• auf das erste Element zugreifen
• das erste Element der Schlange entfernen
• alle Elemente ausgeben
Implementierung
TSchlange
- Kopf : TKnoten
+
+
+
+
+
+
create
istLeer: boolean
einfuegeKnotenein(k : Tknoten)
giberstesElement : TKnoten
entferneErstes
gibSchlangeAus(liste : TStrings)
TSchlange = class
protected //Attribute
kopf : TKnoten;
public //Methoden
constructor create;
destructor destroy;override;
function istLeer : boolean;
function gibErstesElement : TKnoten;
procedure entferneErstes;
procedure fuegeKnotenEin (kn: TKnoten);
procedure gibSchlangeAus (liste: TStrings);
end;
Implementation
27
Schlangeobjekt erzeugen
constructor TSchlange.create;
begin
kopf := TKnoten.create('leer');
end;
Im Konstruktor wird Leerelement als
Kopf erzeugt.
Ein Leerelement erhält einen Verweis
auf erste Element
und zerstören
destructor TSchlange.destroy;
begin
while kopf.gibNachfolger <> nil do
entferneErstes;
kopf.Free;
inherited destroy;
end;
Alle Elemente aus Schlange entfernen
und freigeben
Leerelement freigeben
Destruktor der Vorfahrklasse aufrufen
um das Schlangenobjekt zu zerstören
Klasse TKnoten
28
TKnoten
- inhalt : string;
- nachfolger : TKnoten;
+ create (wert: string);
Die Knoten implementieren das FIFO – Prinzip
+ fuegeKnotenEin (neuerKnoten: TKnoten)
+ gibKnotenAus (liste: TStrings);
+ setzeInhalt (wert: string);
+ setzeNachfolger (k: TKnoten);
+ gibInhalt : string;
+ gibNachfolger : TKnoten;
Einfügen am Ende der Schlange (FIFO – Prinzip)
procedure TKnoten.fuegeKnotenEin (neuerKnoten: TKnoten);
begin
if nachfolger = nil then
nachfolger := neuerKnoten
else
nachfolger.fuegeKnotenEin(neuerKnoten);
end;
Der neue Knoten wird bis zum
letzten weitergereicht
Aufgabe 2
29
Aufgabe 1
Erstellen Sie ein Programm, mit dessen Hilfe die Implementierung der Klasse
„TSchlange“ gestestet werden kann.
Z. B.: Es soll eine Städte [Köln;Frankfurt; ...] erstellt und angezeigt werden.

Es müssen nicht alle Methoden implementiert werden.

Benutzen Sie die vorgegebene Benutzungsoberfläche
Aufgabe 2
Fügen Sie den Knoten das Attribut entfernung hinzu. Zu Testzwecken kann der
Wert zufällig beim Erzeugen des Knotens gesetzt werden.
Ändern Sie die Methode Tknoten.fuegeKnotenEin (...) so ab, dass die Knoten
- abweichend vom FIFO-Prinzip - nach Entfernung geordnet eingefügt werden.
(Prioritäten-Warteschlange)
30
Teil 4
Implementierung des Graphen zum Lageplan
mit Dijkstra Algorithmus
31
OOA-Klassendiagramm
32
Sequenzdiagramm: Weg berechnen
Create()
als besucht
Anhang 1
Entwicklung der
Prioritäten-Warteschlange durch Vererbung
Prioritäten-Warteschlange
34
Im Unterschied zu einer gewöhnlichen Schlange werden die Dinge nach einer Priorität
geordnet eingefügt und gemäß dieser Priorität wieder entnommen.
Eine solche Schlange ist also im Prinzip eine geordnete Liste.
TPKnoten
- inhalt : string;
- nachfolger : TKnoten
- entfernung : integer
+ create (wert: string);
 Die Knoten erhalten ein weiteres Attribut
(Priorität), nach denen sie geordnet werden.
 Außerdem ändert sich das Einfügen.
 Ein neuer Knoten wird so lange weitergereicht,
bis er einen Knoten höherer Priorität erreicht.
+ fuegeKnotenEin(nK :TKnoten)
+ gibKnotenAus (liste: TStrings);
+ setzeInhalt (wert: string);
+ setzeNachfolger (k: TKnoten);
+ gibInhalt : string;
+ gibNachfolger : TKnoten;
Mit Hilfe von Vererbung kann der größte
Teil des bisher geschriebenen Codes
wiederverwendet werden.
Spezialisierung der Knoten
35
TKnoten
- inhalt : string;
- nachfolger : TKnoten
Basisklasse
- Die Methode fuegeKnotenEin() wird als
virtuelle Methode deklariert
+ create (wert: string)
+ fuegeKnotenEin (nK: TKnoten)
...
Ist ein - Beziehung
TPKnoten
- entfernung : integer
+ create (wert: string; e : integer)
+ fuegeKnotenEin(nK :TKnoten)
Abgeleitete Klasse
- erhält ein Prioritätsattribut
- überschreibt die Methode zum Einfügen
Implementierung
36
TKnoten = class
protected
inhalt : string;
nachfolger : TKnoten;
public
constructor create (wert: string);
procedure fuegeKnotenEin (nk: TKnoten); virtual;
...
end;
Basisklasse
TP_Knoten = class(TKnoten)
Abgeleitete klasse
protected
entfernung : integer;
public
constructor create (wert: string; e : integer);
procedure fuegeKnotenEin (nK : TKnoten); override;
procedure setzeEntfernung (e: integer);
function gibEntfernung : integer;
end;
Der statische Konstruktor wird
neu implementiert (ersetzt).
Klasse TPSchlange
37
TSchlange
- Kopf : TKnoten
Die Klasse TPSchlange wird von TSchlange
abgleitet.
Es wird lediglich den Konstruktor geändert.
+ create
...
constructor TPSchlange.create;
TPSchlange
+ create
begin
kopf := TP_Knoten.create('');
end;
Dem geerbten Attribut Kopf wird ein TP_KnotenObjekt zugewiesen
Anhang 2
38
Delphi verfügt über eine vordefinierte Klasse „TList“. Informieren Sie sich über
diese Klasse mit der Delphi-Hilfe. Implementieren Sie dann die Prioritätenschlange
mit dieser vordefinierten Klasse „TList“.
TList
+ Count: integer
+ Items[pos: integer]: Pointer
+ create
+ Delete(pos: integer)
+ Insert(pos: integer; obj: Pointer)
...
TList verwaltet eine Liste von Zeigern auf Objekte.
Mit Hilfe des Properties (Attribut) Items kann
auf jede Objektreferenz per Index zugegriffen
werden.
Der Parameter Index enthält den Index auf das
Objekt, wobei das erste den Index 0 hat, der
letzt den Index Count-1.
Beispiel:
var Knotenliste : Tlist;
Knoten : TKnoten
...
for i := 0 to Knotenliste.Count-1 do
begin
Knoten := Tknoten(Liste.items[i]);
Knoten.gibAus(....);
end;
Durch Typumwandlung erhält man Zugriff
auf das Objekt an der Position i
Anhang 2
39
Implementierung der Schlange mit einem TList-Objekt
TSchlange
- liste : TList
+
+
+
+
+
+
create
istLeer: boolean
einfuegeKnotenein(k : Tknoten)
giberstesElement : TKnoten
entferneErstes
gibSchlangeAus(liste : TStrings)
Die Klasse TSchlange liefert eine eingeschränkte
Schnittstelle zum geschützten TList-Objekt.
Die Verwaltung der Objekte wird an das TListObjekt delegiert.
Stringlisten
TStringList
+ Count: integer
+ Strings: array[0..] of string
+ create
+ delete(p: integer)
+ insert(p: integer; s: String)
...
Für Listen von Strings bietet Delphi die Klasse
TStringList.
Einige Attribute (Properties) und Operationen sind
im nebenstehenden Klassendiagramm aufgeführt.
Die Bedeutung der Bestandteile kann mit der
Delphi-Hilfe ermittelt werden.
Die Delphi-Komponenten TListBox und TMemo
enthalten ein Stringlistenobjekt.
Aufgabe 3
40
Aufgabe 1
Implementieren Sie mit Hilfe der Delphi-Klasse TList eine Stapel.
(Lineare Liste, die das FIFO-Prinzip realisiert)
TStapel
- liste : TList
+
+
+
+
+
+
create
istLeer: boolean
einfuegeKnotenein(k : Tknoten)
giberstesElement : TKnoten
entferneErstes
gibStapel(liste : TStrings)
Aufgabe 2
Entwickeln Sie eine gemeinsame Oberklasse, aus der dann Stapel und Schlange
abgeleitet werden.
Quellen
41
•
Klaus Becker: Weiterbildungslehrgang X "Informatik für Gymnasien“ Kurs
http://informatik.bildung-rp.de/weiterbildungsmaterial/lehrgang-x-2005-2008/kurs-5.html

MathPrisma:
http://www.matheprisma.uni-wuppertal.de/Module/Graphen/index.htm

H.W. Lang FH Flensburg : http://www.inf.fh-flensburg.de/lang/algorithmen/graph/

swisseduc.ch :
Informatik Graphbench: http://www.swisseduc.ch/informatik/graphbench/

M. Pohlig:
www.pohlig.de

Jürgen Dehmer, A. Sessler, G. Liebrich
Projekt: Tauglichkeitstester
http://www.lehrer.uni-karlsruhe.de/~za714/informatik/infkurs
Herunterladen