Upload
ishild-rehrig
View
112
Download
0
Embed Size (px)
Citation preview
Kürzeste WegeKürzeste Wege
Implementierung des Algorithmus von Dijkstra
Helmut Paulus Speyer, 5.-7.11.07
Teil 1Teil 1
Objektorientierte Modellierung von Graphen
3 GraphenGraphen
Ein Graph besteht aus– einer Menge von Knoten (Objekten)
und– einer Menge von Kanten
(Beziehungen), die die Knoten verbinden.
Ein Graph besteht aus– einer Menge von Knoten (Objekten)
und– einer Menge von Kanten
(Beziehungen), die die Knoten verbinden.
Ein Graph beschreibt eine Struktur aus Objekten und den Beziehungen zwischen ihnen.
Klassische Probleme Eulersche Wanderungen
Hamiltonsche Rundreisen
Labyrinthproblem
Problem des Handlungsreisenden
Kürzeste Wege
4 Algorithmus von DijkstraAlgorithmus 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}
{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 DijkstraAlgorithmus von Dijkstra
{Eingabe: Graph G; Startknoten s, Zielknoten z des Graphen}
für alle Knoten w setze dg(w) = ∞ setze dg(s) = 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 dg(u) = ∞ füge u in WS ein falls dg(u) > dg(w) + g({w,u}) setze dg(u) = dg(w)+g({w,u})
{Ausgabe: gewichteter Abstand dg(w) des Zielknotens z vom Startknoten s}
{Eingabe: Graph G; Startknoten s, Zielknoten z des Graphen}
für alle Knoten w setze dg(w) = ∞ setze dg(s) = 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 dg(u) = ∞ füge u in WS ein falls dg(u) > dg(w) + g({w,u}) setze dg(u) = dg(w)+g({w,u})
{Ausgabe: gewichteter Abstand dg(w) des Zielknotens z vom Startknoten s}
Abgewandelte Version:
Vorteil:
Geringerer Rechenaufwand bei einer einmaligen Suche
6 Algorithmus von DijkstraAlgorithmus von Dijkstra
A
B
CD
E
F
6
101
2
12
25
16
20
56
A
B
CD
E
F
6
101
2
12
25
16
20
56
Nach Ausführung
31
0
10
12 1
5
20
Jeder besuchte Knoten enthält den minimalen Abstand zum Startknoten, sowie einen Verweis zu seinem Vorgänger im Pfad (lineare Liste).
Gesucht:
Kürzester Weg von A nach E
7 Implementierung von GraphenImplementierung von Graphen
TKnoten- name : string
- kanten : Tkantenliste
- anzahlkanten : integer
- entfernung : integer
- nachfolger, vorgaenger : TKnoten+ create(n : string; x,y : integer)
+ fuegeKantehinzu(nachbar : Tknoten; e : integer)
TKante
- entfernung : integer- zielKnoten :TKnoten+ create(k : TKnoten; e : integer)
+ gibEntfernung : integer+ gibNachbar : TKnoten
*
1
Objektorientierte Lösung:
Jeder Knoten ist ein Objekt
Jede Kante ist ein Objekt
*TGraph
- anzahlKnoten : integer
- knoten : Tknotenliste- initialisiere
+ create
+ 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
8 ZielsetzungZielsetzung
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 Graphen wird als Bild auf der Benutzungsoberfläche angezeigt.
/2/ Man kann sich einen kürzesten Weg von einem eingegebenen Start- zu 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 Teil 2
Grafik mit Delphi
10 Zeichenfläche TCanvasZeichenfläche TCanvas
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
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);...
Brush : TBrush
Pen : TPen
Font : TFont...
Pinsel – Füllfarbe, Muster ... Stift – Linienfarbe, Stil ...
Schriftart – Farbe, Schrifttyp ...
Der Koordinatenursprung (0,0) ist in der linken oberen Ecke einer Komponenten, die ein Canvas-Objekt zur Verfügung stellen.
TCanvas-Werkzeuge Pen, Brush und Font, zuständig für bestimmte Teilaufgaben:
11 Wie erhält man ein TCanvas-Objekt?Wie erhält man ein TCanvas-Objekt?
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.
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.
12 ObjekthierarchieObjekthierarchie
Das Bild-Objekt Bild vom Typ TImage verwaltet über das Attribut Canvas ein Leinwand-Objekt der Klasse TCanvas, das wiederum ein Zeichenstift-Objekt der Klasse TPen und ein Malpinsel-Objekt der Klasse TBrush verwaltet.
Die entsprechenden Attribute Pen und Brush werden als Property zur Verfügung gestellt.
Beispiel: Blaues Rechteck
Bild.Canvas.Brush.Color := clbue;
Bild.canvas.rectangle(10,10,100,20);
Beispiel: Blaues Rechteck
Bild.Canvas.Brush.Color := clbue;
Bild.canvas.rectangle(10,10,100,20);
Pinselfarbe blau
Rechteck mit der linken oberen Ecke am Punkt (X1, Y1) und der rechten unteren Ecke am Punkt (X2, Y2).
13 Aufgaben 1Aufgaben 1
1. Testen Sie das Beispielprogramm Grafiktest.exeVariieren Sie verschiedene Modi der Pinsel und StifteTesten Sie insbesondere den NotXOR-Füllmodus
2. Entwickeln Sie ein Programm, das die Bilddatei Lageplan.jpg im Formular anzeigt.
Teil 3Teil 3
Entwicklung einer Warteschlange
15 Datentyp SchlangeDatentyp Schlange
Eine Schlange realisiert das Prinzip FIFO (First In First Out),
d. h. die Ausgabe erfolgt in gleicher Reihenfolge wie die Eingabe.
Spezialisierte Schlange:
:Knotennachfolger =
name =A
:Knoten
nachfolger =
name =B
:SchlangeKopf =
...
nil
kennt
kennt
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.
Jedes Element kennt einen Nachfolger
Kopf
16 Allgemeine SchlangeAllgemeine Schlange
:Knotennachfolger =
inhalt =
:Knoten
nachfolger =
inhalt =
:SchlangeKopf =
...
nil
kennt
kennt
Schlange für beliebige Objekte
:Object :Object
Jedes Element erhält ein Inhaltsobjekt
17 Klasse TSchlangeKlasse TSchlange
TSchlange
- Kopf : TKnoten
+ create+ istLeer: boolean+ einfuegeKnotenein(k : Tknoten)+ giberstesElement : TKnoten+ entferneErstes+ gibSchlangeAus(liste : TStrings)
Operationen (Fähigkeiten)• 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 Element ausgeben
Implementierung
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;
18 ImplementationImplementation
constructor TSchlange.create;
begin
kopf := TKnoten.create('leer');
end;
Im Konstruktor wird Zeigerelement auf das Kopfelement erzeugt.
Das Leerelement erhält eine Referenz auf das erste Element
Schlangeobjekt erzeugen
destructor TSchlange.destroy;
begin
while kopf.gibNachfolger <> nil do entferneErstes;
kopf.Free;
inherited destroy;
end;
Alle Elemente aus der Schlange entfernen und freigeben
Leerelement freigeben
Destruktor der Vorfahrklasse aufrufen, um das Schlangenobjekt zu zerstören
und zerstören
19 Klasse TKnotenKlasse TKnoten
TKnoten- inhalt : string;
- nachfolger : TKnoten;+ create (wert: string);
+ fuegeKnotenEin (neuerKnoten: TKnoten)
+ gibKnotenAus (liste: TStrings);
+ setzeInhalt (wert: string);
+ setzeNachfolger (k: TKnoten);
+ gibInhalt : string;
+ gibNachfolger : TKnoten;
Die Knoten implementieren das 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
Einfügen am Ende der Schlange (FIFO – Prinzip)
FIFO-Knoten
20 Aufgabe 2Aufgabe 2
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)
Teil 4Teil 4
Entwicklung der
Prioritäten-Warteschlange durch Vererbung
22 Prioritäten-WarteschlangePrioritäten-Warteschlange
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);
+ fuegeKnotenEin(nK :TKnoten)
+ gibKnotenAus (liste: TStrings);
+ setzeInhalt (wert: string);
+ setzeNachfolger (k: TKnoten);
+ gibInhalt : string;
+ gibNachfolger : TKnoten;
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.
Mit Hilfe von Vererbung kann der größte Teil des bisherigen Codes wiederverwendet werden.
23 Spezialisierung der KnotenSpezialisierung der Knoten
TKnoten- inhalt : string;
- nachfolger : TKnoten
+ create (wert: string)
+ fuegeKnotenEin (nK: TKnoten)
...
TPKnoten- entfernung : integer
+ create (wert: string; e : integer)
+ fuegeKnotenEin(nK :TKnoten)
Ist ein - Beziehung
Abgeleitete Klasse
- erhält ein Prioritätsattribut
- überschreibt die Methode zum Einfügen
Basisklasse
- Die Methode fuegeKnotenEin() wird als virtuelle Methode deklariert
FIFO-Knoten
Prioritäts-Knoten
24 ImplementierungImplementierung
TPKnoten = class(TKnoten)
protected
entfernung : integer;
public
constructor create (wert: string; e : integer);
procedure fuegeKnotenEin (nK : TKnoten); override;
procedure setzeEntfernung (e: integer);
function gibEntfernung : integer;
end;
TKnoten = class protected inhalt : string; nachfolger : TKnoten; public constructor create (wert: string); procedure fuegeKnotenEin (nk: TKnoten); virtual; ... end;
Der statische Konstruktor wird neu implementiert (ersetzt).
Basisklasse
Abgeleitete klasse
Die virtuelle Methode zum Einfügen wird überschrieben.
25 Klasse TWarteschlangeKlasse TWarteschlange
constructor TWarteschlange.create;
begin
kopf := TPKnoten.create('');
end;
TSchlange
- Kopf : TKnoten
+ create ...
TWarteSchlange
+ create
Die Klasse TWarteschlange wird von TSchlange abgleitet.
Es wird lediglich den Konstruktor geändert.
Dem geerbten Attribut Kopf wird ein TPKnoten-Objekt zugewiesen
26 AnhangAnhang
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
27 AnhangAnhang
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 TList- Objekt delegiert.
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.
Stringlisten
28 Aufgabe 3Aufgabe 3
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.
29 QuellenQuellen
• 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
Teil 5Teil 5
Implementierung des Graphen zum Lageplan
und mit Dijkstra Algorithmus
31 OOA-KlassendiagrammOOA-Klassendiagramm