Computer Science - Hochschule Bochum

Werbung
Computer Science
Prof. Dr. Katrin Brabender
Labor für
Angewandte Informatik und Datenbanken
Version: 15.08.2006
WS 2006/2007 Computer Science
Seite 1
Inhalte der Vorlesung
Algorithmen und Datenstrukturen
• Lineare und Nichtlineare Datenstrukturen
• Formale Beschreibung von Algorithmen
• Suchalgorithmen
• Wörterbücher
•
Hash-Verfahren
•
Binäre Suchbäume, Balancierte Bäume etc.
• Sortieralgorithmen
• Geometrische Algorithmen
• Graphen Algorithmen
Grundlagen der Automatentheorie
WS 2006/2007 Computer Science
Seite 2
1
Literatur
Bernd Breutmann: Data and Algorithms, Fachbuchverlag Leipzig,2th edition, 2001.
Ralf Hartmut Güting, Stefan Dieker: Datenstrukturen und Algorithmen, 2. Auflage, 2003.
H.-P. Gumm, M. Sommer: Einführung in die Informatik, 5. Auflage, 2002.
Volker Heun: Grundlegende Algorithmen. Vieweg, Braunschweig Wiesbaden, 2000.
Gunter Saake, Kai-Uwe Sattler: Algorithmen und Datenstrukturen. Eine Einführung mit Java.
dpunkt.Verlag, 3.Auflage 2006.
Thomas Ottmann, Peter Widmayer: Algorithmen und Datenstrukturen. Spektrum
Akademischer Verlag, Heidelberg Berlin, 3. Auflage, 1996.
Uwe Schöning: Theoretische Informatik-kurzgefasst, Spektrum Akademischer Verlag,
Stuttgart Leipzig, 4. Aufl., 2001.
Gottfried Vossen, Kurt-Ulrich Witt: Grundlagen der Theoretischen Informatik mit
Anwendungen, Vieweg, 2. Aufl. ,2002.
Niklaus Wirth: Algorithmen und Datenstrukturen, B.G. Teubner, Stuttgart Leipzig, 1999.
WS 2006/2007 Computer Science
Seite 3
Teil 1:
Algorithmen und Datenstrukturen
WS 2006/2007 Computer Science
Seite 4
2
Datenstrukturen
•
Algorithmen und Datenstrukturen sind ein zentrales Thema in der
Informatik.
•
Algorithmen operieren nur dann effektiv mit Daten, wenn diese für einen
Algorithmus geeignet strukturiert sind.
•
Die Wahl der richtigen Datenstruktur entscheidet über effiziente
Laufzeiten der Algorithmen.
WS 2006/2007 Computer Science
Seite 5
Datentypen
Unter Datentyp versteht man eine Menge von Werten und von
Operationen.
Eine Operation ist dabei eine Verknüpfung, die einer festen Anzahl von
Eingabedaten ein Ergebnis zuordnet.
Zu einem bestimmten Datentyp gehört immer ein charakteristischer Satz
von Operationen.
Beispiele
Jede Programmiersprache hat einen Datentyp, der die Menge der
ganzen Zahlen integer, reellen Zahlen real, Zeichen char und Wahrheitswerte boolean repräsentiert.
WS 2006/2007 Computer Science
Seite 6
3
Datentyp:
Boolean
Werte:
true, false
Operationen:
or, and, xor :
Boolean x Boolean -> Boolean
not
:
Boolean -> Boolean
true, false
:
-> Boolean
Gleichungen: Für alle x, y aus Boolean gilt
x or y = y or x
x and y = y and x
true or x = true
true and x = x
false or x = x
false and x = false
x xor y = (x and not y) or (not x and y)
In Java werden and , or , not , xor durch && , || , ! , ^ dargestellt.
WS 2006/2007 Computer Science
Seite 7
Datentyp:
Integer
Werte:
alle ganzen Zahlen
Operationen:
+, -, *, div, mod :
Integer x Integer -> Integer
Gleichungen: Für alle x, y aus Integer gilt
0+x=x
0*x=0
(x div y)* y + x mod y = x
x – y = x + (-y)
(-x div y) = -(x div y) = x div –y
(-x mod y) = - (x mod y)
x mod –y = x mod y
In Java, C und C++ werden div und mod durch / und % dargestellt.
WS 2006/2007 Computer Science
Seite 8
4
Datentyp:
Real
Werte:
alle reellen Zahlen
Operationen:
+, -, *, / :
Real x Real -> Real
sqrt, ln, sin, exp : Real -> Real
Gleichungen: Für alle x, y aus Real gilt
0+x=x
0*x=0
sprt(x) * sqrt(x) = x ….
WS 2006/2007 Computer Science
Seite 9
Datentyp:
Char
Werte:
alle ASCII-Zeichen
Operationen: chr, ord
Gleichungen: ord(chr(n)) = n, chr(ord(c))) = c
Die grundlegenden Datentypen, d.h. integer, real, boolean und char
bezeichnet man als Elementare- oder Primitive Datentypen.
WS 2006/2007 Computer Science
Seite 10
5
Pointer
Ein Pointer (Zeiger) ist ein Verweis auf eine Objektrepräsentation im
Hauptspeicher, d.h. eine Adresse im Hauptspeicher.
Falls ein Zeiger auf kein Objekt zeigt, hat er den Wert NULL (NIL). Man
nennt ihn Nullpointer.
In Programmiersprachen wie C und Pascal werden Zeiger explizit
gekennzeichnet.
Sie müssen erzeugt werden. Wird der Speicherplatz nicht mehr benötigt,
d.h. zeigt kein Zeiger mehr auf ihn, so muss der belegte Speicherplatz bei
diesen Programmiersprachen vom Programmierer wieder freigegeben
werden (z.B. mit dispose(p))
WS 2006/2007 Computer Science
Seite 11
Zeiger in Java
In Java werden Objekte (d.h. Instanzen von Klassen) durch
Zeiger realisiert.
Man spricht von Referenzdatentypen im Gegensatz zu den
primitiven Datentypen.
Durch die sog. Garbage Collection wird der nicht mehr benötigte
Speicher automatisch freigegeben.
WS 2006/2007 Computer Science
Seite 12
6
Beispiel: Referenzdatentype u. primitiver Datentyp
public class Int {
private int wert;
//Konstruktor
Int (int wert) {
this.wert = wert;
}
}
Mit den Variablen
int i = 2;
Int j = new Int(2);
Die Variable i repräsentiert einen Wert vom Typ int.
Die Variable j referenziert ein Objekt vom Typ Int.
WS 2006/2007 Computer Science
Seite 13
Definition
Eine Datenstruktur ist eine Sammlung von Knoten derselben Klasse oder
desselben Typs, deren Organisation und Zugriff klar definiert sind.
Ein Knoten kann ein Objekt oder auch primitive Datentypen, wie eine Zahl
sein.
Wir werden uns zunächst mit den linearen Datenstrukturen beschäftigen.
WS 2006/2007 Computer Science
Seite 14
7
Lineare Datenstrukturen
Linear bedeutet, dass es zu jedem Element (Knoten) höchstens
einen Vorgänger und höchstens einen Nachfolger gibt.
Die einfachste lineare Datenstruktur ist das Array.
WS 2006/2007 Computer Science
Seite 15
Arrays
•
Ein Array ist die einfachste lineare Datenstruktur.
•
In einem Array wird eine endliche Menge von Elementen des selben
Typs gespeichert.
•
Die einzelnen Elemente heißen Komponenten und können über
Indizes angesprochen werden.
•
Man bezeichnet die k-te Komponente eines Arrays a mit a[k] oder ak
•
In Java und C werden die Komponenten eines Arrays ab 0
nummeriert. Mit length erhält man die Anzahl der Komponenten des
Arrays
WS 2006/2007 Computer Science
Seite 16
8
Bemerkung zu Arrays
•
Die Größe eines Arrays wird zum Zeitpunkt der Erstellung des Arrays
festgelegt, danach kann sie nicht mehr verändert werden.
Ein Array ist eine lineare, statische Datenstruktur.
Nachteile eines Arrays
•
Belegung von viel Speicherplatz bei großen Datenmengen
•
u. U. aufwendiges Einfügen von Elementen
•
Array kann „voll“ sein
WS 2006/2007 Computer Science
Seite 17
Listen
Eine Liste ist eine Folge von Elementen, in der an beliebiger Stelle neue
Elemente eingefügt oder vorhandene Elemente entfernt werden können.
Wie kann man Listen implementieren?
Einfachste Methode: Listenelemente werden in einem Array gespeichert.
Nachteil:
• Beim Anlegen muss festgelegt werden, wie viele Datensätze maximal
gespeichert werden
• Speicherplatz wird u.U. verschenkt oder Array ist voll
• Einfügen eines Elementes bedeutet Verschiebung anderer Elemente
=> Implementierung durch lineare dynamische Datenstruktur.
WS 2006/2007 Computer Science
Seite 18
9
Lineare dynamische Datenstrukturen
Dynamische Datenstrukturen passen ihre Größe der Anzahl der
Daten an, die sie aufnehmen.
WS 2006/2007 Computer Science
Seite 19
Einfach verkettete Liste
•
Eine einfach verkettete Liste ist eine lineare dynamische
Datenstruktur.
•
Sie besteht aus einer Folge von Zellen / Knoten.
•
Jeder Knoten enthält neben dem „Daten-Element“ einen Zeiger
(Referenz) Next auf den folgenden Knoten der Liste.
•
Die Liste hat einen Anfangszeiger, der auf den ersten Knoten
zeigt.
•
Der Zeiger des letzten Knotens zeigt auf NULL.
Anfang
Inhalt
1
Inhalt
2
Inhalt
Inhalt
3
n
NULL
WS 2006/2007 Computer Science
Seite 20
10
Entfernen und Einfügen eines Elementes erfolgen durch einfaches
Kopieren der Referenzen.
Durch Garbage Collection wird die entfernte Zelle aus dem Speicher
entfernt.
Zunächst betrachten wir eine Implementierung einer verketteten Liste.
WS 2006/2007 Computer Science
Seite 21
Knoten einer Liste in Java
public class Knoten {
private Object inhalt;
private Knoten next;
next ist wieder vom Datentyp
Knoten
// Konstruktor:
Knoten (Object inhalt) {
this.inhalt = inhalt;
}
Knoten (Object inhalt, Knoten next) {
this.inhalt = inhalt;
this.next = next;
}
//get- und set-Methoden
public Knoten getNext(){
return next;
}
WS 2006/2007 Computer Science
Seite 22
11
public Object getInhalt(){
return inhalt;
}
public void setNext(Knoten next){
this.next = next;
}
public void setInhalt(Object inhalt){
this.inhalt = inhalt;
}
}
WS 2006/2007 Computer Science
Seite 23
Implementierung einer verketteten Liste
public class Liste {
private Knoten anfang;
private Knoten cursor;
//Ermittlung der Laenge der Liste
int laenge () {
Knoten cur = anfang;
int l = 0;
while (cur != null) {
l++;
cur = cur.getNext();
}
return l;
}
WS 2006/2007 Computer Science
Seite 24
12
//Hilfsmethoden zum korrekten Setzen der Referenz Cursor
boolean istGueltigePosition (int p) {
return (p >= 0) && (p < laenge() );
}
void setzeCursor (int p){
cursor = null;
if (istGueltigePosition (p) ) {
Knoten cur = anfang;
for (int i = 0; i < p;i++)
cur = cur.getNext();
cursor = cur;
}
}
WS 2006/2007 Computer Science
Seite 25
//Methode, die Inhalt des Objektes eines Knotens liefert
Object inhalt (int p){
setzeCursor (p);
return cursor.getInhalt();
}
//Methode zum Löschen des p-ten Knotens in Liste
void loesche (int p) {
if (istGueltigePosition(p)){
if (p == 0) // Loesche 1. Zelle
anfang = anfang.getNext();
else {
setzeCursor(p-1);
cursor.setNext(cursor.getNext().getNext());
}
}
}
WS 2006/2007 Computer Science
Seite 26
13
//Methoden zum Einfügen eines Objektes in Liste
void einsetzenNach (int p, Object e){
setzeCursor (p);
if (cursor != null) {
Knoten z = new Knoten (e, cursor.getNext());
cursor.setNext(z);
}
}
void einsetzenVor (int p, Object e){
if (p > 0)
einsetzenNach (p-1,e);
else {// Einsetzen am Anfang
Knoten z = new Knoten (e, anfang);
anfang = z;
}
}
void einsetzenAnfang (Object e){
Knoten z = new Knoten (e,anfang);
anfang = z;
}
}
WS 2006/2007 Computer Science
Seite 27
Spezielle Listen - Stapel (stack) und Schlange (queue)
Operationen können nur an einem Ende ausgeführt werden.
Stapel
Einfügen und Entfernen nur am Kopf (Anfang) der Liste, d.h.
LIFO (last in, first out);
Abfertigung in umgekehrter Reihenfolge der Ankunft.
Schlange
Einfügen am Ende, Entfernen am Kopf, d.h. FIFO (First in, first out)
Abfertigung in Reihenfolge des Eintreffens.
WS 2006/2007 Computer Science
Seite 28
14
Die Datenstrukturen Keller (Stack)
Ein Keller oder Stack hat die Eigenschaften
•
Knoten sind in einer Folge angeordnet
•
Nur der Anfang des Stacks ist zugänglich
•
Knoten werden am Anfang hinzugefügt
•
Knoten werden vom Anfang entfernt.
•
Der Keller kann nicht durchsucht werden, nur der Knoten am
Anfang ist sichtbar.
Aufgrund dieser Eigenschaften bezeichnet man einen Keller aus als
LIFO-Liste (Abkürzung für Last In First Out).
WS 2006/2007 Computer Science
Seite 29
Eine Anwendung von Stacks ist die Verwaltung rekursiver Methoden.
Die wichtigsten Methoden für einen Stack sind die Methoden push()
und pop() zum Einfügen und Entfernen aus dem Keller.
Um die Funktionalität von diese beiden Methoden zu verstehen,
implementieren wir eine Klasse Keller mit den beiden Methoden.
Keller soll durch ein Array dargestellt werden.
WS 2006/2007 Computer Science
Seite 30
15
Implementierung eines Kellers
class Keller{
private int laenge;
private Object[] kellerarray;
private int top; //index der nächsten freien Zelle
//Konstruktor
Keller (int laenge){
this.laenge = laenge;
kellerarray = new Object[laenge];
top = 0; //Setzen von top auf die erste Position
}
WS 2006/2007 Computer Science
Seite 31
Die Methoden push() und pop()
void push (Object x){
if (top >= laenge)
System.out.println("Keller voll");
else {
kellerarray[top] = x;
top++;
}
}
Object pop(){
if (top > 0){
top--;
return kellerarray[top];
}
else
return null;
}
}
WS 2006/2007 Computer Science
Seite 32
16
Die Datenstrukturen Schlange (Queue)
Eine Schlange oder Queue hat die Eigenschaften
•
Knoten sind in einer Folge angeordnet
•
Es gibt zwei Enden, den Anfang (head) und das Ende (tail)
•
Knoten werden am Ende hinzugefügt
•
Knoten werden vom Anfang entfernt.
•
Die Schlange kann von Anfang bis zum Ende durchsucht werden
Aufgrund dieser Eigenschaften bezeichnet man eine Schlange auch als
FIFO-Liste (Abkürzung für First In First Out).
WS 2006/2007 Computer Science
Seite 33
Eine Schlange kann mittels einer verketteten Liste oder mit Hilfe
eines Arrays implementiert werden. Wir werden hier –wie schon beim
Stack- das Array nehmen.
Die zwei wichtigsten Methoden sind
enqueue(element) zum Einfügen in eine Queue und dequeue()
zum Entfernen aus einer Queue.
WS 2006/2007 Computer Science
Seite 34
17
Implementierung einer Schlange
class Schlange{
private
private
private
private
int laenge;
Object[] schlangearray;
int head, tail;
boolean istleer;
//Konstruktor
Schlange (int laenge){
this.laenge = laenge;
head = tail = 0;
istleer = true;
schlangearray = new Object[laenge];
}
WS 2006/2007 Computer Science
Seite 35
Die Methode enqueue()
void enqueue (Object x){
if ((tail == head) && (istleer == false)){
System.out.println("Queue ist voll");
}
else{
schlangearray[tail] = x;
tail++;
istleer = false;
if (tail == laenge)
tail = 0;
}
}
WS 2006/2007 Computer Science
Seite 36
18
Die Methode dequeue()
Object dequeue(){
if ((tail == head) &&(istleer == true)){
System.out.println("Queue ist leer");
return null;
}
else {
Object inhalt = schlangearray[head];
head++;
if (head == laenge)
head = 0;
if (head == tail)
istleer = true;
return inhalt;
}
}
}
WS 2006/2007 Computer Science
Seite 37
Zusammenfassung
Behandelt wurden lineare Datenstrukturen
•
Eine Datenstruktur ist eine Sammlung von Knoten derselben Klasse
oder desselben Typs, deren Organisation und Zugriff klar definiert
sind.
•
Linear bedeutet, dass jedes Element höchstens einen Vorgänger und
höchstens einen Nachfolger hat.
•
Dynamisch bedeutet, dass sich die Größe der Datenstruktur zur
Laufzeit verändern kann
•
Arrays sind lineare statische Datenstrukturen, dessen Elemente vom
selben Typ sind
•
Einfach verkettete Listen sind lineare dynamische Datenstrukturen
WS 2006/2007 Computer Science
Seite 38
19
Nichtlineare Datenstrukturen
Bäume
•
Bäume gehören zu den fundamentalen Datenstrukturen der
Informatik.
•
Sie können als zweidimensionale Verallgemeinerung von Listen
gesehen werden.
•
In Bäumen kann man nicht nur Daten, sondern auch relevante
Beziehungen der Daten untereinander speichern
•
Bäume sind Datenstrukturen, die besonders für das schnelle Finden
von Daten geeignet sind
WS 2006/2007 Computer Science
Seite 39
Grundbegriffe innerhalb eines Baumes
Ein Baum besteht aus einer Menge von Knoten, die untereinander durch
Kanten verbunden sind.
Führt von Knoten A zu Knoten B eine Kante, so schreibt man A -> B und
sagt A ist Elternknoten (parent, Vater) von B oder B ist Kind von A (Sohn).
Ein Pfad von A nach B ist eine Folge von Knoten und Kanten, die von A
nach B führen. A ->X1 ->X2->…->B. (A ist dabei Elternknoten von X1….)
Die Länge des Pfades definiert man als Anzahl der Kanten auf dem Pfad.
Knoten ohne Kind nennt man Blatt.
Alle anderen Knoten heißen innere Knoten.
WS 2006/2007 Computer Science
Seite 40
20
Ein Baum muss folgende Axiome erfüllen
• Es gibt genau einen Knoten ohne Elternknoten. Diesen nennt man
Wurzel.
• Jeder andere Knoten hat genau einen Eltern-Knoten.
Definition Baum (rekursiv)
Ein Baum ist leer oder er besteht aus einer Wurzel W und einer leeren oder
nicht leeren Liste B1,B2,…,Bn von Bäumen.
Von W zur Wurzel W i von Bi führt jeweils eine Kante.
WS 2006/2007 Computer Science
Seite 41
Tiefe eines Knotens k
Länge des Pfades von der Wurzel zu diesem Knoten k.
Höhe eines Baumes
0 falls leerer Baum, sonst Maximum der Tiefe seiner Knoten.
Beispiele von Bäumen:
• Stammbäume
• Dateibäume (Knoten sind Dateien oder Verzeichnisse, Kanten
führen von einem Verzeichnis zum Unterverzeichnis)
• Organisationsstruktur eine Firma
WS 2006/2007 Computer Science
Seite 42
21
Binärbäume
Bäume mit der Eigenschaft, dass jeder Knoten nur 2 Kinder hat.
Definition Binärbaum
Ein Binärbaum ist
•
leer oder
•
besteht aus einem Knoten – Wurzel genannt – und zwei
Binärbäumen, dem rechten und linken Teilbaum.
WS 2006/2007 Computer Science
Seite 43
Traversierung eines Binärbaums
Eine Traversierung eines Baumes zählt alle Elemente, die in einem
Baum sind, in einer bestimmten Reihenfolge auf.
Die wichtigsten Durchläufe sind
Preorder
Postorder
Inorder
Levelorder
WS 2006/2007 Computer Science
Seite 44
22
Ein binärer Baum B heißt vollständiger Baum, wenn er folgende Form
hat:
Also:
für jedes k mit k < Höhe (B) gilt:
•
die k-te Schicht ist voll besetzt (ein Baum beginnt auf Schicht 0,
d.h. B besitzt 2k Knoten der Tiefe k)
•
die letzte Schicht ist, von links nach rechts gelesen, bis zu
einem Punkt P besetzt
WS 2006/2007 Computer Science
Seite 45
Heaps
Ein Array a heißt Heap, wenn es ein vollständiger Baum ist, für den gilt
a[i] >= a[2i+1] und a[i] >= a[2(i+1)]
Ein Heap ist also ein Binärbaum mit den beiden Eigenschaften
1. Form
2. Ordnung: Entlang jedes Pfades von einem Knoten zur Wurzel sind die
Knoteninhalte aufsteigend sortiert
WS 2006/2007 Computer Science
Seite 46
23
Algorithmen
Algorithmen sind Verfahren zur schrittweise Lösung von Problemen.
Sie sind Grundlage für jedes Computer-Programm.
Beispiel: Bestimmung des größten gemeinsamen Teilers
Gegeben seine zwei positive ganze Zahlen m und n.
Bestimme den größten gemeinsamen Teiler von m und n.
1. (Vertausche m und n) m ↔n
2. (Übertrage an n den Wert n modulo m) n ← n % m
3. (Ist n größer 0?) Falls n >0 gehe zurück zu 1.
Falls n = 0 ist Algorithmus beendet. Ergebnis ist m.
WS 2006/2007 Computer Science
Seite 47
Pseudocode
Algorithmen sind Programmiersprachen unabhängig. Eine
gebräuchliche Art Algorithmen darzustellen ist die Benutzung von
Pseudocode.
Pseudocode ist eine künstliche Sprache, die den höheren
Programmiersprachen wie Java, C oder Pascal ähnelt.
Anhand des Pseudocodes kann der Algorithmus direkt in die
entsprechende Programmiersprache übertragen werden.
WS 2006/2007 Computer Science
Seite 48
24
Notation im Pseudocode
1. In der ersten Zeile erscheint der Name des Algorithmus, gefolgt
von den geforderten Parametern
2. Einrücken zeigt Blockstruktur. Zusätzlich wird eine Blockstruktur
durch {} gekennzeichnet.
3. Als Kontroll-Strukturen benutzen wir die Schlüsselwörter while,
for, if…else
4. Kommentare werden durch // angezeigt.
5. Wir benutzen Semikolons am Ende einer Anweisung
WS 2006/2007 Computer Science
Seite 49
Basiselemente eines Algorithmus
1. Operationen
wie n % m, a + b
2. Anweisungen und Zuweisungen
unterschieden werden input, output Anweisungen.
Sie sind zuständig für den Datenfluss ins und aus dem System
Zuweisungen werden durch ← ausgedrückt (m ← n, m erhält
Wert von n);
m ↔ n bedeutet t ← m; m ← n; n ← t
3. Kontrollstrukturen
Es gibt drei Arten von Kontrollstrukturen
Sequenz-Struktur, Verzweigung, Schleife
WS 2006/2007 Computer Science
Seite 50
25
•
Sequenz-Struktur, d.h. Anweisungen werden hintereinander
ausgeführt
In Pseudocode
anweisung 1;
M
anweisung n;
•
Verzweigung (if-Anweisung)
In Pseudocode
if (bedingung){
anweisung a1;…;anweisung am;
}
else {
anweisung b1;…;anweisung bn;
}
WS 2006/2007 Computer Science
Seite 51
•
Schleife oder Wiederholungs-Struktur (while oder for)
In Pseudocode
while (bedingung)
{anweisung 1;…;anweisung n;}
oder
M
for (i = 1 to m)
{anweisung 1;…;anweisung n;}
WS 2006/2007 Computer Science
Seite 52
26
Definition Algorithmus
Ein Algorithmus ist eine endliche Folge von Anweisungen. Ein
Algorithmus benötigt eine Menge von Werten (diese kann auch leer sein)
als Input und generiert eine Menge von Werten als output (diese darf
nicht leer sein).
WS 2006/2007 Computer Science
Seite 53
Ein Algorithmus hat vier wichtige Eigenschaften
1. (endlich) Nach einer Anzahl von endlichen Schritten ist der
Algorithmus beendet
2. (exakt) Jeder Schritt des Algorithmus ist präzise definiert
3. (elementar) Alle Operationen sind auf elementare Operationen
zurückzuführen
4. (input) Ein Algorithmus hat null oder mehr input-Daten
5. (output) Ein Algorithmus hat ein oder mehrere output-Daten
WS 2006/2007 Computer Science
Seite 54
27
Kriterien für die Qualität von Algorithmen
1. Korrektheit
2. Einfach zu verstehen (besonders für Wartung wichtig)
3. Einfach zu implementieren
4. Geringe Laufzeit und geringe Plattenplatz (Komplexität des
Algorithmus)
Bemerkung:
Die einzelnen Kriterien können sich auch widersprechen,
z.B. können effiziente Algorithmen sehr unübersichtlich sein.
WS 2006/2007 Computer Science
Seite 55
Die Laufzeit T von Algorithmen
Unter der Laufzeit T(n) eines Algorithmus auf einer bestimmten InputMenge der Größe n versteht man die Anzahl der auszuführenden
Schritte. Für jede Anweisung wählt man eine konstante Zeit t0. Diese
Zeit t0 ist vom Algorithmus unabhängig und nur von dem Computer
abhängig. Gewöhnlich setzt man t0 = 1.
Es wird unterschieden
worst-case:
bestimmt die obere Grenze der Laufzeit für jeden Input
best-case:
bestimmt die untere Grenze der Laufzeit für jeden Input
average-case: bestimmt die Laufzeit für einen typischen Input, d.h.
den Durchschnitt
WS 2006/2007 Computer Science
Seite 56
28
T(n)
Notation
ln n, log n, log 10 n
logarithmische
Zeitkomplexität
n, n2, n3
polynomiale
Zeitkomplexität
2n, en
exponentielle
Zeikomplexität
Ein Algorithmus heißt effizient, wenn er mindestens polynomiale
Zeitkomplexität hat.
WS 2006/2007 Computer Science
Seite 57
Durch Weglassen von multiplikativen und additiven Konstanten wird
nur noch das Wachstum einer Laufzeitfunktion T(n) betrachtet:
Definition (O -Notation)
Sei g (n) eine gegebene Funktion. Mit O(g(n)) bezeichnet man die
Menge aller Funktionen, die kleiner gleich einer Konstanten multipliziert
mit g ab einem bestimmten endlichen Wert n 0 ist.
D.h.
f
wächst höchstens so schnell wie
g.
Anders ausgedrückt:
{
O ( g (n)) = f (n) | ∃c ∈ R + , n0 ∈ N : 0 ≤ f (n) ≤ c ∗ g (n) ∀ n ≥ n0
Statt T ( n) ∈ O ( g ( n)) schreibt man auch
}
T (n) = O( g(n))
WS 2006/2007 Computer Science
Seite 58
29
Zusammenfassung
•
Ein Algorithmus ist eine endliche Folge von Anweisungen, die durch
3 Kontrollstrukturen kontrolliert werden.
•
Es werden Inputdaten in Output-Informationen transformiert
•
Die Komplexität wird gemessen durch das Zählen der Anzahl der
Anweisungen, die ausgeführt werden; Grundlage ist die RAM, ein
idealisiertes mathematisches Modell eines Computers
•
Ein Algorithmus mit mindestens polynomialer Zeitkomplexität ist
effizient.
WS 2006/2007 Computer Science
Seite 59
Suchalgorithmen
Formulierung des Suchproblems
In einem Behälter A befinden sich eine Reihe von Elementen.
Prüfe, ob ein Element e ∈ A existiert, das eine bestimmte Eigenschaft
P(e) erfüllt.
Behälter sind z.B. Arrays, Listen, Bäume etc.
Wir betrachten zunächst Algorithmen auf Arrays.
Die Werte im Array seien Zahlen.
WS 2006/2007 Computer Science
Seite 60
30
Das Suchproblem lautet also für Arrays:
Sei a[] ein Array der Länge n.
Prüfe, ob Element e im Array vorhanden ist, d.h. existiert ein i für das
gilt: a[i] == e für i = 0,…,n-1.
WS 2006/2007 Computer Science
Seite 61
Lineare Suche
Die lineare Suche ist der einfachste Suchalgorithmus. Das Array wird
der Reihe nach durchsucht. Die Länge des Arrays sei n.
Der Algorithmus lautet
LinSuche (a[], e) {
for (i = 0; i < n; i++){
if (a[i] = = e)
return i;
}
return –1; //ungültiger Index
}
Es gilt Tbest = O (1)
Taverage = Tworst = O(n)
WS 2006/2007 Computer Science
Seite 62
31
Binäre Suche
Voraussetzung: Suche auf geordnetem bzw. sortiertem Array a.
Definition: a heißt geordnet (oder sortiert) wenn gilt:
∀ i : 0 ≤ i ≤ n − 2 ist a[i ] ≤ a[i + 1]
WS 2006/2007 Computer Science
Seite 63
Idee der Binären Suche
Sei 0 = min, n - 1 = max
Wähle Index m mit min ≤ m ≤ max
(meist m = (min+max)/2)
-
Falls e = a[m] => Fertig, Element gefunden
-
Falls e < a[m] => Suche weiter im Bereich [min,m-1],
d.h. max = m-1
-
Falls e > a[m] => Suche weiter im Bereich [m+1;max],
d.h. min = m+1
Abbruch, falls min > max, dann ist e kein Element des Arrays.
WS 2006/2007 Computer Science
Seite 64
32
algorithm RekBinSuche (a[], e, min, max) {
if (min > max)
return –1;
m
am
← (min +
← a[m];
max) / 2;
if (e = = am)
return m;
if (e < am)
return
RekBinSuche (a[],e,min,m-1);
if (e > am)
return RekBinSuche (a[],e,m+1,max);
}
return –1;
WS 2006/2007 Computer Science
Seite 65
Die binäre Suche ist für große Datenmengen weit effizienter als die lineare
Suche.
Es gilt:
Taverage = Tworst = O (log 2 n )
Im besten Fall ist nur ein Aufruf des Suchalgorithmus nötig.
Aber: Die Elemente müssen sortiert vorliegen.
Daher oft bei großen nicht sortierten Datenmengen sinnvoll:
Kopiere alle Elemente in Array, sortiere Array, wende binäre Suche an.
WS 2006/2007 Computer Science
Seite 66
33
Wörterbücher (Dictionaries)
Als Wörterbuch wird eine Menge von Elementen eines gegebenen
Grundtyps bezeichnet, auf der man die Operationen Suchen, Einfügen
und Entfernen von Elementen ausführen kann.
Man nimmt meistens an, dass alle Elemente über einen in der Regel
ganzzahligen Schlüssel (key) eindeutig identifizierbar seien.
Such-, Einfüge- und Entferne-Operationen werden nur auf dem jeweiligen
Schlüssel durchgeführt.
Implementierungsmöglichkeiten: Listen, Hashtabellen, Bäume.
WS 2006/2007 Computer Science
Seite 67
Streu-Verfahren (Hash-Verfahren)
Die Grundidee von Hashverfahren besteht darin, aus dem Wert eines
zu speichernden Mengenelementes seine Adresse im Speicher zu
berechnen. Den Speicher zur Aufnahme der Mengenelemente fasst
man als eine Menge von Körben B0,…BB-1 auf. Der Wertebereich D,
aus dem die Mengenelemente stammen können, kann beliebig groß
sein (meist |D| >> B).
WS 2006/2007 Computer Science
Seite 68
34
Eine Hashfunktion h : D → {0,..., B − 1} , B Anzahl der Körbe, ordnet
jedem Schlüssel x ∈ D einen Index h(x) mit 0 ≤ h( x) ≤ B −1 zu.
h(x) = b mit b Korb.
Eine Hashfunktion sollte folgende Eigenschaften haben:
•
surjektiv, d.h. sie sollte alle Körbe erfassen
•
sie sollte die zu speichernden Schlüssel möglichst gleichmäßig
über alle Körbe verteilen
•
effizient zu berechnen sein
WS 2006/2007 Computer Science
Seite 69
Werden mehrere Werte auf den selben Korb abgebildet, so nennt man
das Kollision.
Hashverfahren unterscheiden sich in der Art der Kollisionsbehandlung.
Beim offenem Hashing nimmt man an, dass ein Korb beliebig viele
Schlüssel aufnehmen kann.
Beim geschlossenen Hashing kann ein Korb nur eine kleine konstante
Anzahl b von Schlüsseln aufnehmen; falls mehr als b Schlüssel auf
einen Korb fallen, entsteht ein Überlauf.
WS 2006/2007 Computer Science
Seite 70
35
Offenes Hashing (Open Hashing)
Ein Korb kann beliebig viele Schlüssel aufnehmen.
Zur Implementierung
Die Hashtabelle ist ein array der Größe B, das aus verketteten linearen
Listen besteht. D.h. aus Zeigern, die auf Elemente des Typs Knoten
zeigen.
NULL
WS 2006/2007 Computer Science
Seite 71
Beim Einfügen, Entfernen und Suchen eines Schlüssels k wird beim
Open Hashing jeweils die Liste Hashtabelle[i] mit i = h(k) durchlaufen.
Einfügen
Das neue Element wird als erstes Element in diese Liste eingefügt.
Suchen
Beim Suchen eines Elementes die entsprechende Liste sukzessiv
durchsucht.
WS 2006/2007 Computer Science
Seite 72
36
Die einfachste Hash-Funktion ist die Modulo-Funktion
h(x) = x mod B
mit Körben 0,…,B-1
Zeitberechnung:
O (1) Durchschnitt und worst-case bei Einfügen,
da stets erstes Element.
Nachteil bei Open-Hashing: Hoher Speicherplatzbedarf.
Die schlechteste Hashfunktion lautet h(x) = Konstante für alle x aus D.
WS 2006/2007 Computer Science
Seite 73
Geschlossenes Hashing (Closed Hashing)
•
Jeder Korb kann nur eine kleine konstante Anzahl b (meist b = 1) von
Schlüsseln aufnehmen;
•
Wir nehmen b = 1 an:
•
Falls mehr als 1 Schlüssel auf einen Korb fällt, entsteht ein Überlauf:
Damit ist für das geschlossene Hashing die Kollisionsbehandlung von
entscheidender Bedeutung:
WS 2006/2007 Computer Science
Seite 74
37
Kollisionsbehandlung durch rehashing
Neben der Hashfunktion h = h0 existieren weitere Hashfunktionen h1,…hB-1,
die für einen gegebenen Schlüssel x die Körbe h(x), h1(x),h2(x)…
untersuchen.
Einfügen
Sobald ein freier oder als gelöscht markierter Korb gefunden ist, wird x dort
eingetragen.
Suchen
Bei der Suche nach x wird h(x), h1(x),h2(x)… betrachtet bis entweder x
gefunden oder erster freier Korb in dieser Folge gefunden. Dann ist x nicht
vorhanden.
WS 2006/2007 Computer Science
Seite 75
Wichtig: Es muss unterschieden werden, ob Zelle frei oder gelöscht ist.
Eine einfache Rehash-Funktion ist
hi ( x ) = ( h ( x ) + i ) mod B , 1 ≤ i ≤ B − 1
Man nennt diese Rehash-Funktion Lineares Sondieren. Sie hat den
Nachteil, dass Elemente oft nicht einmal sondern mehrfach rehashed
werden müssen.
Besser: quadratisches Sondieren
hi ( x ) = ( h ( x ) + i 2 ) mod B , 1 ≤ i ≤ B − 1
WS 2006/2007 Computer Science
Seite 76
38
Binäre Suchbäume
Definition
Ein binärer Suchbaum hat die Eigenschaften:
-
leer oder
-
besteht aus einem Knoten – Wurzel genannt- und zwei binären
Suchbäumen, dem linken und rechten Teilbaum.
Der Inhalt des Wurzelknotens ist größer oder gleich allen
Elementen im linken Suchbaum und kleiner als alle Elemente im
rechten Suchbaum.
Binäre Bäume sind Wörterbuch-Datenstrukturen.
WS 2006/2007 Computer Science
Seite 77
Implementierung von Binären Suchbäumen in Java.
Die Inhalte der Knoten sind hier Integer Werte.
class Knoten {
private int inhalt;
private Knoten links;
private Knoten rechts;
// Konstruktoren:
public Knoten (int inhalt) {
this.inhalt = inhalt;
}
public Knoten(int inhalt, Knoten links,Knoten rechts){
this.inhalt = inhalt; this.links = links;
this.rechts = rechts;
}
public int getInhalt(){
return inhalt;
}
WS 2006/2007 Computer Science
Seite 78
39
public Knoten getLinks(){
return links;
}
public Knoten getRechts(){
return rechts;
}
public void setInhalt(int inhalt){
this.inhalt = inhalt;
}
public void setLinks(Knoten links){
this.links = links;
}
public void setRechts(Knoten rechts){
this.rechts = rechts;
}
}
WS 2006/2007 Computer Science
Seite 79
Nachdem die Klasse Knoten definiert wurde, kann nun die Klasse Baum
definiert werden. Ein Baum besteht aus einer Wurzel vom Datentyp
Knoten, sowie aus Methoden zum Einfügen, Löschen und Suchen
eines Knoten.
public class Baum {
private Knoten wurzel;
public Knoten getWurzel(){
return wurzel;
}
//… Methoden
}
WS 2006/2007 Computer Science
Seite 80
40
Wir nehmen für die Operationen Suchen, Einfügen und Entfernen an,
dass keine Duplikate im Baum vorhanden sind.
Suchen eines Elementes x innerhalb eines Binären Suchbäumen B
Vergleiche x mit Wurzel W:
Es treten drei Fälle auf
x = W => Element gefunden
x < W => Suche rekursiv im linken Teilbaum von B
x > W => Suche rekursiv im rechten Teilbaum von B
WS 2006/2007 Computer Science
Seite 81
Implementierung der Suche eines Elementes innerhalb eines
Binären Suchbaumes in Java
boolean suche (int e){
if (wurzel == null)
return false;
else
return rekSuche (e,wurzel);
}
boolean rekSuche (int e, Knoten k){
if ( k == null)
return false;
if ( e == k.getInhalt())
return true;
if (e < k.getInhalt())
return rekSuche (e, k.getLinks());
else
return rekSuche (e, k.getRechts());
}
WS 2006/2007 Computer Science
Seite 82
41
Einfügen eines Elementes x in einen Binären Suchbäumen B
Falls Baum noch leer => Lege x als neue Wurzel an
Falls Baum nicht leer => Suche richtige Position im Baum und lege
neuen Knoten an dieser Stelle an.
WS 2006/2007 Computer Science
Seite 83
Implementierung des Einfügens eines Elementes in einen Binären
Suchbaum
void einfuegen (int e){
if (wurzel == null)
wurzel = new Knoten (e);
else
rekEinfuegen (e,wurzel);
}
void rekEinfuegen (int e, Knoten k){
if (e < k.getInhalt())
if (k.getLinks() == null)
k.setLinks(new Knoten (e));
else rekEinfuegen (e,k.getLinks());
else
if (k.getRechts() == null)
k.setRechts(new Knoten (e));
else rekEinfuegen (e,k.getRechts());
}
WS 2006/2007 Computer Science
Seite 84
42
Löschen eines Elementes x aus einem Binären Suchbaum B
Das Löschen ist schwieriger als das Einfügen und Suchen.
Das zu löschende Element x kann irgendwo in der Mitte sein,
eventuell an der Wurzel. Dann muss umgehängt werden.
WS 2006/2007 Computer Science
Seite 85
Mögliche Fälle:
a) x ist ein Blatt => einfaches Löschen
b) x hat einen leeren linken oder rechten Teilbaum =>
Ersetze x durch die Wurzel des anderen Teilbaums
c) x hat nichtleeren linken und rechten Teilbaum =>
Ersetze x durch den kleinsten Wert seines rechten Teilbaumes
um die Sortierung beizubehalten.
Dies kann ein Umhängen nach sich ziehen.
WS 2006/2007 Computer Science
Seite 86
43
Wir verwenden zwei Methoden zum Löschen:
loesche1 für Fälle a und b, d.h. Knoten hat höchstens 1 Kind
loesche2 für Fall c, d.h. Knoten hat zwei Kinder
void loescheKnoten(Knoten k){
if (k.getLinks() == null || k.getRechts() == null)
loesche1(k);
else
loesche2(k);
}
WS 2006/2007 Computer Science
Seite 87
Beim Löschen zeigt es sich als sinnvoll, die Knoten für Binäre Bäume
noch durch eine weitere Referenz zu ergänzen:
Jeder Knoten erhält neben den Referenzen auf den linken und rechten
Teilbaum auch noch eine Referenz nach oben auf den Elternknoten.
public class Knoten
private
private
private
private
{
int inhalt;
Knoten links;
Knoten rechts;
Knoten oben;
// Konstruktoren
//get- und set-Methodedn
}
WS 2006/2007 Computer Science
Seite 88
44
void loesche1(Knoten k) {//k hat max. 1 Kind
//Bestimme Kind von k
Knoten enkel;
if (k.getLinks() == null)
enkel = k.getRechts();
else
enkel = k.getLinks();
if (k == wurzel){
wurzel = enkel;
return;
}
//Ab hier klar: Elternknoten von k existiert
Knoten eltern = k.getOben();
// Verbinde Elternknoten zum Enkel
if (eltern.getLinks() == k)
eltern.setLinks(enkel);
else eltern.setRechts(enkel);
//Verbinde Enkel zum Elternknoten
if (enkel != null)
enkel.setOben(eltern);
}
}
WS 2006/2007 Computer Science
Seite 89
Zum Löschen eines Knotens mit zwei Kindern, muss dieser durch den
kleinsten Wert seines rechten Teilbaumes ersetzt werden.
Daher muss eine Methode zum Bestimmen des Minimums definiert
werden:
Knoten sucheMin (Knoten k){
if (k == null)
return k;
while (k.getLinks() != null)
k = k.getLinks();
return k;
}
D.h. das kleinste Element eines binären Suchbaumes findet man, indem
man dem linken Teilbaum Pointer solange folgt, bis ein Knoten mit leerem
linken Teilbaum angetroffen wird.
WS 2006/2007 Computer Science
Seite 90
45
Implementierung des Löschens eines Knotens mit zwei Kindern
void loesche2(Knoten k) {//k hat genau 2 Kinder
Knoten min = sucheMin(k.getRechts());
//Kopiere Inhalt nach oben
k.setInhalt(min.getInhalt());
loesche1(min);
}
WS 2006/2007 Computer Science
Seite 91
Bemerkung:
Der Zeitbedarf für die Operationen Suchen, Einfügen und Löschen ist
im Durchschnitt O(log2n).
WS 2006/2007 Computer Science
Seite 92
46
Behandlung von Duplikaten in Binären Suchbäumen
Es gibt verschiedene Möglichkeiten Duplikate in einen binären
Suchbaum einzufügen.
Eine Möglichkeit ist, Duplikate der Wurzel stets zur neuen Wurzel des
linken Teilbaumes zu machen:
Die Methode rekEinfuegen verändert sich dann wie folgt:
WS 2006/2007 Computer Science
Seite 93
void rekEinfuegen (int e, Knoten k){
// Falls Duplikate eingefuegt werden
if (e == k.getInhalt()){
Knoten neu = new Knoten (e);
if (k.getLinks() != null)
k.getLinks().setOben(neu);
neu.setLinks(k.getLinks());
k.setLinks(neu);
neu.setOben(k);
return;
}
// Ende Duplikate einfuegen
if (e < k.inhalt)
if (k.getLinks() == null)
k.setLinks (new Knoten (e));
else rekEinfuegen (e,k.getLinks());
else
if (k.getRechts() == null)
k.setRechts(new Knoten (e));
else rekEinfuegen (e,k.getRechts());
}
WS 2006/2007 Computer Science
Seite 94
47
Beim Löschen muss der zu löschende Knoten durch die Liste aller
Duplikate des kleinsten Knotens des rechten Teilbaumes ersetzt
werden.
Den Inhalt des ersten Knotens dieser Liste kopiert man in den zu
löschenden Knoten, die Restliste fügt man zwischen diesen und
seinem linken Kind ein.
In einem zweiten Schritt muss dann der unten übrig gebliebene oberste
Knoten aus der vormaligen Liste von Duplikaten gelöscht werden. Dies
geschieht mit der Methode loesche1.
WS 2006/2007 Computer Science
Seite 95
Implementierung des Löschens eines Knotens mit zwei Kindern falls
Duplikate im Minimum vorhanden
void loesche2(Knoten k) { //k hat genau 2 Kinder
Knoten min = sucheMin(k.getRechts());
// Beginn: Beruecksichtigung von Duplikaten
min.setLinks(k.getLinks());
if (min.getLinks() != null)
min.getLinks().setOben(min);
while (min.getInhalt() == min.getOben().getInhalt())
min = min.getOben();
k.setLinks(min.getLinks());
if (k.getLinks() != null)
k.getLinks().setOben(k);
min.setLnks(null);
// Ende Duplikate
//Kopiere Inhalt nach oben
k.setInhalt(min.getInhalt());
loesche1(min);
}
WS 2006/2007 Computer Science
Seite 96
48
Balancierte Bäume
Damit auch im Worst Case ein geringer Zeitbedarf für die drei Operationen
Suchen, Einfügen und Löschen entsteht, eignen sich besonders gut
Balancierte Bäume als Datenstruktur.
Balanciert:
• Alle Blattknoten haben gleiche Tiefe
• Alle Operationen haben im Worst Case Zeitbedarf von O(log n).
Beispiele für Balancierte Bäume sind AVL-Bäume, 2-3 Bäume, B-Bäume.
WS 2006/2007 Computer Science
Seite 97
AVL-Bäume
Ein binärer Suchbaum heißt AVL-Baum, wenn sich für jeden Knoten des
Baums die Höhen seiner Unterbäume höchstens um 1 unterscheiden.
Dazu wird jedem Knoten eine zusätzliche Komponente b hinzugefügt.
b heißt der Balancefaktor des Knotens und gibt die Differenz der Höhe des
rechten Unterbaums und der Höhe des linken Unterbaums an.
Also gilt für AVL-Bäume b ∈{−1,0,1}
WS 2006/2007 Computer Science
Seite 98
49
Einfügen in einen AVL- Baum
Fügt man ein Element in einen AVL-Baum ein, so kann es passieren,
dass der Balancefaktor eines Teilbaums ungleich –1, 0, 1 ist.
Dann läuft man an der Einfügestelle den Suchpfad entlang zur Wurzel
zurück und prüft an jedem Knoten, ob die Höhendifferenz zwischen
linkem und rechtem Teilbaum noch innerhalb der vorgeschriebenen
Grenzen liegt.
Falls nein, dann führt man Rotation bzw. Doppelrotation durch.
WS 2006/2007 Computer Science
Seite 99
2-3 Bäume
Wesentliches Merkmal:
•
Alle Pfade von der Wurzel zu einem Blatt sind gleich lang (Balance)
Weiterhin gilt
•
Echte Informationen stehen nur an den Blättern
•
Alle inneren Knoten haben 2 oder 3 Kinder
•
Sortierung wie bei binären Suchbäumen von links nach rechts
WS 2006/2007 Computer Science
Seite 100
50
Abbildung eines 2-3 Baumes
Inneren Knoten enthalten jeweils den Wert des kleinsten Knotens im
zweiten Teilbaum (klz) und ggf. den Wert des kleinsten Knotens im
dritten Teilbaum (kld).
Für die Höhe H eines 2-3 Baumes gilt für die Anzahl N der Blätter:
2 H ≤ N ≤ 3H
also
log 3 N ≤ H ≤ log 2 N .
Damit gilt: H ist O(log N), zur Basis 2 oder 3.
WS 2006/2007 Computer Science
Seite 101
Suchverfahren im 2-3 Baum
Am inneren Knoten:
Falls x < klz, suche im 1. Teilbaum
Falls klz
≤ x < kld oder kld nicht vorhanden, suche im 2. Teilbaum
Falls x ≥ kld, suche im 3. Teilbaum
Falls 3. Teilbaum nicht vorhanden oder x < kld, suche im 2. Teilbaum
WS 2006/2007 Computer Science
Seite 102
51
Einfügen in 2-3 Baum
Zunächst Platz für x suchen. Dann
•
Wenn innerer Knoten k auf vorletzter Ebene nur 2 Kinder hatte, x
geeignet einfügen (dann 3 Kinder). Daher ggf. inneren Knoten
anpassen.
•
Wenn innerer Knoten schon 3 Kinder hatte, diesen Knoten unter
Anpassung der Verwaltungsfunktion in k, k`spalten. Kleinere Kinder
zu k, größere zu k`. Falls Elternknoten von k auch schon drei
Kinder, geht die Spaltung nach oben weiter.
•
Sonderfall: Hatte die Wurzel bisher schon 3 Unterbäume, so werden
Pfade verlängert. Es geschieht kein Ausgleich zwischen Nachbarn.
WS 2006/2007 Computer Science
Seite 103
Entfernen aus 2-3 Baum
Hat ein innerer Knoten k nach Entfernen nur noch 1 Kind, ein
benachbarter Knoten jedoch 3 Kinder, dann:
Ausgleich mit Nachbarknoten: erst von links Kind holen, falls nicht
möglich, dann von rechts.
Falls dies nicht möglich ist, folgt Entfernung nach oben weiter, ggf.
muss die Wurzel gelöscht werden.
WS 2006/2007 Computer Science
Seite 104
52
Allgemeine B-Bäume
Sind eine Verallgemeinerung von 2-3 Bäumen.
•
Sie haben die folgenden Eigenschaften:
•
Alle Pfade von der Wurzel zu einem Blatt sind gleich lang.
•
Echte Informationen nur an den Blättern.
•
Sortierung von links nach rechts.
•
Zahl der Verweise bei inneren Knoten sind k,…, 2k-1 mit k ≥ 2.
•
Zahl der Verweise bei Wurzel 2,…,2k-1.
Ein 2-3 Baum ist ein B-Baum für k = 2 .
WS 2006/2007 Computer Science
Seite 105
Entfernen aus B- Baum
1. Ausgleich unter Nachbarn, wenn Unterlauf < k und ein Nachbar
abgeben kann (d.h. > k).
2. Verschmelzung, wenn Unterlauf und kein Nachbar abgeben kann
(z.B. k-1 und Nachbar hat k Kinder), dann Verschmelzung zu 2k-1
Kinder.
3. Falls damit auf nächst höherer Stufe Unterlauf, rekursiv weiter.
4. Hat Wurzel dann nur 1 Verweis, dann Wurzel löschen.
WS 2006/2007 Computer Science
Seite 106
53
Einfügen in B- Baum
1. Spaltung in zwei Blöcke, falls Überlauf > 2k-1.
2. Falls dadurch auf nächst höherer Stufe Überlauf, rekursiv weiter.
3. Bei Spaltung der Wurzel, neue Wurzel mit zwei Verweisen anlegen.
Bei B-Bäumen, insbesondere bei sehr großem k, sind die Weglängen
zu den Blättern von der Wurzel sehr gering.
WS 2006/2007 Computer Science
Seite 107
Zusammenfassung
• Wörterbücher sind Datenstrukturen auf denen man die Operationen
Suchen, Einfügen und Entfernen von Elementen ausführen kann.
• Implementierungsmöglichkeiten durch Listen, Hashtabellen, Bäume.
• Beim Hashing unterscheidet man zwischen Offenem- und
Geschlossenem Hashing.
• Binäre Suchbäume haben für alle drei Operationen einen Zeitbedarf
von O(log2n) im Durchschnitt. Worst Case liegt bei O(n).
• Balancierte Bäume, wie 2-3 Bäume, B-Bäume haben ein Zeitbedarf
von O(log n) im Worst Case. Sie sind für den Zugriff großer
Datenmengen auf externen Datenträgern geeignet.
WS 2006/2007 Computer Science
Seite 108
54
Sortierverfahren
Gegeben: Unsortierte Folge a1,…,an von Elementen.
Gesucht: Sortierte Folge mit ai ≤ ai+1 .
Wir werden die verschiedenen Sortieralgorithmen auf Arrays betrachten,
d.h. das Problem lautet:
Sei a ein Array mit a[0],...,a[n-1].
Gesucht wird ein sortiertes Array mit a[i] ≤ a[i+1]; i = 0,...,n-2
WS 2006/2007 Computer Science
Seite 109
Eine Lösungsmöglichkeit:
Elemente nach und nach in binären Suchbaum bzw. in 2-3 Baum
eintragen. Dies geschieht für 2-3 Bäume im Durchschnitt und Worst Case
in O(n log n) Schritten und für binäre Suchbäume im Mittel in O(n log n)
Schritten.
Gesucht: bessere Sortierverfahren.
Es gibt eine ganze Reihe von Sortieralgorithmen.
Wir werden den BubbleSort, QuickSort, MergeSort sowie den HeapSort
betrachten.
WS 2006/2007 Computer Science
Seite 110
55
Bubble-Sort
Bubble-Sort ist ein elementares Sortierverfahren.
Idee des Bubble-Sort
Bubble-Sort bringt in mehreren Durchläufen jeweils das kleinste Element
des Restarrays an die erste Position. Im ersten Durchlauf ist das
Restarray gleich dem ganzen Array. Im zweiten Durchlauf fehlt gegenüber
dem ersten Durchlauf das erste Element. In jedem Durchlauf bringt man
das kleinste Element nach vorne, in dem vom letzten Element her jedes
Element mit seinem Vorgänger verglichen wird. Falls es kleiner als sein
Vorgänger ist, wird es vertauscht.
Der Algorithmus kann abgebrochen werden, wenn nichts mehr vertauscht
werden muss.
WS 2006/2007 Computer Science
Seite 111
Der Algorithmus kann in Pseudocode wie folgt formuliert werden:
algorithm BubbleSort(a[]){
b ← true;
j ← a.length;
while(b){ //true
b ← false;
for (i = a.length-1;i > a.length-j;i--)
if (a[i] < a[i-1]){
a[i] ↔ a[i-1];
b ← true;
}
j--;
}
}
b gibt an, ob noch etwas vertauscht wird. Falls false, wird der
Algorithmus abgebrochen.
WS 2006/2007 Computer Science
Seite 112
56
Anmerkungen zum Bubble-Sort
Bubble-Sort ist ein recht langsames Sortierverfahren.
Für den Zeitaufwand gilt:
n −1
(n-1) + (n-2) + ...+ 1 =
∑
i =1
i =
n ( n − 1)
= O (n 2 )
2
WS 2006/2007 Computer Science
Seite 113
„Divide and Conquer“ Algorithmen
Divide and Conquer Algorithmen beschreiben folgende Problemlösestrategie
•
Zerlege das Problem P in die Teilprobleme P1,...,Pn .
•
Löse das Problem rekursiv für jede Teilmenge.
•
Setze die Lösung L von P als Kombination der Lösungen L1,..., Ln der
Teilmengen zusammen.
Ein Vertreter dieser Algorithmen ist das Sortierverfahren QuickSort.
WS 2006/2007 Computer Science
Seite 114
57
QuickSort
QuickSort wurde 1962 von dem britischen Informatiker C.A.R.Hoare
entwickelt. Damals waren noch keine schnellen Sortierverfahren
bekannt.
QuickSort ist ein rekursiver Algorithmus. Rekursive Algorithmen
galten früher als ineffizient.
WS 2006/2007 Computer Science
Seite 115
Der Algorithmus QuickSort arbeitet wie folgt:
Gegeben sei das unsortierte Array a[0],…,a[n-1] der Länge n.
Divide: Teile die Elemente des Arrays a[l],…,a[r] in zwei Teilarrays
a[l],…,a[k] und a[k+1],..,a[r], so dass gilt a[i] ≤ a[j] für alle l ≤ i ≤ k
und k+1 ≤ j ≤ r . (Im ersten Schritt ist l = 0 und r = n-1)
Diesen Schritt nennt man Partitionierung.
Conquer: Sortiere die beiden Teilarrays rekursiv indem QuickSort für
die Teilarrays aufgerufen wird.
WS 2006/2007 Computer Science
Seite 116
58
Wie erfolgt die Partitionierung?
Zu Beginn der Partitionierung wird ein Index p ausgewählt. Der Wert des
Arrays an der Stelle p, d.h. a[p] bezeichnet man als Pivot Element.
Von links her wird gesucht, bis erstes Element a[l] ≥ Pivot gefunden, von
rechts her wird gesucht, bis erstes Element a[r] ≤ Pivot gefunden. Dann
werden diese Elemente vertauscht, wobei l um 1 erhöht und r um 1
erniedrigt wird. Dieser Vorgang wird wiederholt. Das Verfahren bricht ab,
falls l > r wird.
Bemerkung zur Wahl des Pivot-Elementes
Als Pivot Element wählt man meist ein Element in der Mitte des Arrays, d.h.
Pivot = a[(l+r)/2].
WS 2006/2007 Computer Science
Seite 117
Der Algorithmus QuickSort in Pseudocode
algorithm quickSort (a[], begin, end) {
if (begin >= end)
return;
pivot ← a[(begin+end)/2];
l ← begin; r ← end;
Partitionierung
while(l <= r){
while (a[l] < pivot)
l++;
while(a[r] > pivot)
r--;
if (l <= r){
a[l]
a[r] ↔
l++; r--;
}
}
quickSort (a, begin, r);
quickSort (a, l, end);
WS 2006/2007 Computer Science
Seite 118
59
Zeitkomplexität von QuickSort
Worst Case
Aufteilung der Länge n durchweg in Längen n-1 und 1. Dann hat der
Algorithmus die Komplexität O(n2).
Die Aufteilung erfolgt n mal und n Elemente werden durchsucht.
Best Case und Average Case:
Aufteilung in Längen n/2 und n/2.
Dann gilt für die Zeitkomplexität O(n log n).
Die Aufteilung erfolgt log n mal und n Elemente werden durchsucht.
WS 2006/2007 Computer Science
Seite 119
MergeSort
MergeSort ist ein weiterer Divide and Conquer Algorithmus.
MergeSort teilt die ursprüngliche Menge der Datensätze in zwei
Hälften auf. Diese werden sortiert und dann zusammengemischt.
Dabei vergleicht man immer wieder die vordersten Elemente der
sortierten Hälften und entnimmt das kleinste der beiden. Auf diese
Weise verschmelzen (merge) die zwei geordneten Listen zu einer
gemeinsamen geordneten Liste, die alle Elemente der ursprünglichen
zwei Listen enthält.
WS 2006/2007 Computer Science
Seite 120
60
Der Algorithmus MergeSort arbeitet wie folgt
•
Divide, d.h. teile Datensätze in zwei Teilmengen mit jeweils n/2
Elemente
•
Conquer durch Sortierung der beiden Teilmengen rekursiv durch
Aufruf von MergeSort
•
Merge, d.h. mische beide sortierten Teilmengen.
WS 2006/2007 Computer Science
Seite 121
Der Algorithmus MergeSort in Pseudocode
algorithm mergeSort (a[],l, r) {
if (l < r) {
m
←(l+r+1)/2;
mergeSort(a[],l,m-1);
mergeSort(a[],m,r);
merge(a[],l,r,m);
}
}
WS 2006/2007 Computer Science
Seite 122
61
Der Teilalgorithmus Merge stellt sich wie folgt dar:
merge (a[], l, r,m){
//Lege Hilfsarray temp der Laenge r-l+1 an
for (i=0, j=l, k=m; i < temp.length; i++)
if ((k > r) || ((j < m) && (a[j] < a[k]))){
temp[i]
← a[j];
j++;
}
else {
temp[i]
← a[k];
k++;
}
for (i=0; i < temp.length; i++)
a[l+i] ←temp[i];
}
WS 2006/2007 Computer Science
Seite 123
Zeitkomplexität von MergeSort
Best Case und Average Case und Worst Case:
Aufteilung in Längen n/2 und n/2.
Dann gilt für die Zeitkomplexität O(n log n).
Die Aufteilung erfolgt log n mal und n Elemente werden durchsucht.
Da die Aufteilung immer optimal ist (im Gegensatz zu Quicksort), gilt
die Zeitkomplexität auch im Worst Case.
WS 2006/2007 Computer Science
Seite 124
62
Bemerkung zum MergeSort
Der Algorithmus benötigt ein zusätzliches Hilfsarray, in dem die
Elemente gespeichert werden. D.h. es wird zusätzlicher Speicherplatz
benötigt.
WS 2006/2007 Computer Science
Seite 125
HeapSort
HeapSort gilt als sehr guter Sortieralgorithmus. Er garantiert auch im
Worst Case ein Zeitverhalten von O (n log n), d.h. entspricht hier im
Zeitverhalten dem Algorithmus Merge-Sort. Allerdings benötigt HeapSort keinen weiteren Hilfsarray, so dass HeapSort zum Sortieren
erheblich weniger Speicher als MergeSort benötigt.
WS 2006/2007 Computer Science
Seite 126
63
Zur Erinnerung
Ein Array a heißt Heap, wenn es ein vollständiger Baum ist, für den gilt
a[i] >= a[2i+1] und a[i] >= a[2(i+1)]
Ein Heap ist also ein Binärbaum mit den beiden Eigenschaften
1. Form
2. Ordnung: Entlang jedes Pfades von einem Knoten zur Wurzel sind die
Knoteninhalte aufsteigend sortiert
WS 2006/2007 Computer Science
Seite 127
Bevor wir HeapSort definieren, werden wir zunächst zwei
fundamentale Heap Algorithmen behandeln.
Dies sind insert und deleteMax.
WS 2006/2007 Computer Science
Seite 128
64
Einfügen eines Elementes in einen Heap
Damit ein Heap vollständig bleibt, gibt es nur 1 mögliche Position, an
der ein neues Element eingefügt werden kann. Damit kann aber die
Ordnungseigenschaft verletzt werden. Sie muss dann wieder
hergestellt werden.
Insert: Knoten wird mit Elternknoten verglichen und ggf. mit diesem
vertauscht. Dieser Prozess setzt sich nach oben fort, bis
Ordnungseigenschaft für Heap wieder hergestellt.
Diesen Algorithmus nennt man auch UpHeap.
WS 2006/2007 Computer Science
Seite 129
Algorithmus zum Einfügen eines Elementes in einen Heap
algorithm UpHeap(heapo[ ], e) {
//Kopiere Array heapo in ein Array heapt der Laenge
//heapo.length+1
i←heapo.length;
heapt[i] ←e;
while (i > 0) {
hi ← (i-1)/2;
if (heapt[i] > heapt[hi]) {
heapt[hi] ↔ heapt[i];
i←hi;
}
else break;
}
return heapt;
}
WS 2006/2007 Computer Science
Seite 130
65
Löschen des größten Elementes eines Heaps
Das größte Element eines Heaps ist an der Wurzel. Um die Wurzel zu
entfernen, ersetzt man diese durch das am weitesten rechts stehende
Blatt der untersten Ebene. So bleibt die Form-Eigenschaft erhalten.
Um Ordnung zu erhalten muss das neue Element an der Wurzel ggf.
nach unten wandern. Dabei wird es jeweils mit dem größten KindKnoten vertauscht bis Platz gefunden.
Also:
1. Letztes Element in Wurzel kopieren
2. Element nach unten wandern lassen
Diesen Algorithmus nennt man auch DownHeap.
WS 2006/2007 Computer Science
Seite 131
algorithm DownHeap (heapo[ ]) {
l = heapo.length-1;
// Kopiere l-1 Elemente von heapo ab Pos. 1
//in array heapt ab Pos. 1
heapt[0] ← heapo[l];
//letztes Blatt wird an Wurzel
//von heapt gestellt
i ←0; hi ←1;
while (hi < l) {
// linker oder rechter Teilbaum
if (((hi+1) < l) && (heapt[hi] < heapt[hi+1]))
hi++;
if (heapt[i] < heapt[hi]){ // Muss getauscht werden?
heapt[hi]↔ heapt[i]; // Vertausche beide Elemente
i ← hi; hi ← 2*hi+1;
}
else break;
}
return heapt;
}
WS 2006/2007 Computer Science
Seite 132
66
Ablauf des Algorithmus HeapSort
Sei a ein unsortiertes Array (noch kein Heap) der Länge n+1.
1.Phase: „Heap bauen“
a[ 
n − 1 

2
+1],…,a[n] ist ein Teilheap, da diese Knoten keine Kinder
haben. Erweitere diesen Teilheap zu einem Teilheap a[  n
− 1 

2
],…,a[n].
Das Ergebnis ist der Heap a[0],…,a[n].
2. Phase:
Entferne Maximum und schreibe dies beginnend bei a[n] in das Array.
WS 2006/2007 Computer Science
Seite 133
Der Algorithmus HeapSort
algorithm HeapSort (a[]) {
for (i = (a.length-2)/2; i >= 0 ; i--)
ReHeap(a,i,a.length-1);
for (i = (a.length-1); i >= 1;i--) {
a[0]
↔
a[i];
ReHeap(a,0,i-1);
}
}
WS 2006/2007 Computer Science
Seite 134
67
algorithm ReHeap (a[ ],l,r) {
i ←l;
while (2*i+1 <= r) {
if ((2*i+1) < r) {
//Knoten hat zwei Kinder
if (a[2*i+1] > a[2*(i+1)]) //Welches ist das groesste Kind?
hi ←2*i + 1;
else hi ←2*(i+1);
}
else hi ←2*i+1;
//Knoten hatte nur ein Kind
if (a[i] < a[hi]){
a[hi]↔ a[i]; // Vertauschen
i ←hi;
}
else i ←r;
}
}
WS 2006/2007 Computer Science
Seite 135
DistributionSort
DistributionSort ist ein Sortieralgorithmus, der Daten auf
Schlüsselwerten sortiert. Der Sortierschlüssel kann z.B. eine
Ziffernfolge, eine Bytefolge oder eine Zeichenfolge eines festen
Formats sein. Beispiel für Schlüssel sind fünfstellige Postleitzahlen,…
Verfahren: Die zu sortierenden Datensätze werden anhand einer
Ziffernposition in Körbe verteilt und wieder zusammengetragen.
Zuerst wird anhand der letzten Position verteilt, danach nach der
nächsten Position. Die Datensätze sind sortiert, wenn die erste
Position der Ziffernfolge bei der Verteilung erreicht wurde.
WS 2006/2007 Computer Science
Seite 136
68
Beispiel für DistributionSort
Es seien Briefe nach ihren Empfänger – Wohnorten zu sortieren.
Der Sortierschlüssel sei die 5-stellige Postleitzahl.
Für jede der 10 Ziffern 0,1,…,9 wird ein Korb zur Verfügung gestellt.
Sortiert wird dann wie folgt:
1. Verteile alle Briefe auf die 10 Körbe anhand der letzten Ziffer.
2. Zusammenschieben unter Beibehaltung der bisherigen Ordnung
3. Verteilung aller Briefe anhand der vorletzten Ziffer
4. Zusammenschieben…..bis Position 1 erreicht.
WS 2006/2007 Computer Science
Seite 137
Externes Sortieren
Ist die Anzahl der zu sortierenden Datensätze so groß, dass nicht alle
Daten im Hauptspeicher des Rechners gehalten werden können, so
spricht man von externer Sortierung.
Das Problem der externen Sortierung lässt sich auf die interne
Sortierung (Sortierung allein im Hauptspeicher) zurückführen.
Verfahren: Sei D eine große zu sortierende Datei, die nicht im
Hauptspeicher gehalten werden kann.
Teile D in n Teile D1,…,Dn, die jeweils klein genug sind, um intern
sortiert zu werden. Diese werden der Reihe nach sortiert. Die
sortierten Dateien D´1,…,D´n werden zu einer sortierten Datei
D´zusammengefügt. Dies geschieht durch Mischen.
WS 2006/2007 Computer Science
Seite 138
69
Zusammenfassung Sortieralgorithmen
•
Bei den Sortieralgorithmen unterscheidet man zunächst zwischen
externem und internem Sortieren.
•
Die internen Sortierverfahren unterteilen sich in einfache und schnelle
Sortierverfahren.
•
Zu den einfachen Sortierverfahren zählt u.a. Bubble-Sort mit einem
Aufwand von O(n2)
•
Zu den schnellen Sortierverfahren gehören die rekursiven Algorithmen
QuickSort und MergeSort sowie der Algorithmus HeapSort.
•
Rekursive Algorithmen ‚lohnen sich erst‘, wenn die Datenmenge
ausreichend groß ist.
WS 2006/2007 Computer Science
Seite 139
Graphen und Graph-Algorithmen
Einleitung
Ein Graph stellt eine Menge von Objekten zusammen mit einer
Beziehung auf diesen Objekten dar.
Beispiel: Objekte: Personen; Beziehungen: Person A kennt Person B.
Die Bezeichnung Graph stammt von der üblichen ‚graphischen‘
Darstellung:
Objekte werden als Knoten, Beziehungen als Kanten dargestellt.
Eine Beziehung wird im allgemeinen durch eine gerichtete Kante (Pfeil)
dargestellt. Falls die Beziehung symmetrisch ist, wird sie durch eine
ungerichtete Kante dargestellt.
WS 2006/2007 Computer Science
Seite 140
70
Gerichtete Graphen
Definition
Ein gerichteter Graph ist ein Paar G = (V,E), wobei gilt:
(i)
V ist eine endliche, nichtleerer Menge (die Elemente werden Knoten
genannt),
(ii) E ⊆ V x V (die Elemente heißen Kanten).
Eine Kante ist also ein Paar von Knoten.
Die Kante e = (v,w) wird graphisch wie folgt dargestellt: v
→w
WS 2006/2007 Computer Science
Seite 141
Speicher- Darstellung von Graphen
Es gibt verschiedene Datenstrukturen zur Darstellung von Graphen. Die
Art der auszuführenden Operationen bestimmt die Wahl einer
Datenstruktur für einen bestimmten Algorithmus.
Zwei gängige Datenstrukturen sind die Adjazenzmatrix und die
Adjazenzliste.
Sei n = |V| die Anzahl der Knoten und sei V = {v1,...,vn}.
WS 2006/2007 Computer Science
Seite 142
71
Die Adjazenzmatrix
Die Adjazenzmatrix A = (aij) für den Graphen G = (V,E) ist eine
(nxn)-Matrix mit
{
1
falls (vi,vj) ∈ E
0
sonst
aij =
WS 2006/2007 Computer Science
Seite 143
Die Adjazenzlisten
In einer Adjanzenzliste wird für jeden Knoten eine Liste seiner
Nachbarknoten verwaltet.
Über einen Array der Länge n = |V| ist jede Liste direkt zugänglich.
WS 2006/2007 Computer Science
Seite 144
72
Durchlauf von Graphen
Problem:
Systematisch sollen alle Knoten eine Graphen G aufgesucht werden, d.h.
der Graph soll systematisch durchlaufen werden. Hierbei muss darauf
geachtet werden, dass man nicht in Endlosschleifen gerät, wenn der
Graph Zyklen hat. Daher markiert man bereits besuchte Knoten.
Es gibt zwei wesentliche Arten, Graphen zu durchlaufen.
1. Breitendurchlauf (breadth-first-traversal)
2. Tiefendurchlauf (depth-first-traversal)
Beide Verfahren lassen sich mit Hilfe von Bäumen erklären.
WS 2006/2007 Computer Science
Seite 145
Definition
Die Expansion X(v) eines Graphen G in einem Knoten v ist ein Baum,
der wie folgt definiert ist:
1. Falls v keine Nachfolger hat, so ist X(v) der Baum, der nur aus dem
Knoten v besteht.
2. Falls v1,...,vk die Nachfolger von v sind, so ist X(v) der Baum
(v,X(v1),...,X(vk)).
WS 2006/2007 Computer Science
Seite 146
73
Ein Tiefendurchlauf entspricht einem Preorder-Durchlauf der Expansion
von G, der jeweils in einem bereits besuchten Knoten von G
abgebrochen wird.
Ein Breitendurchlauf besucht die Knoten der Expansion ebenenweise,
d.h. zuerst die Wurzel, danach alle Knoten auf Level 1, danach auf Level
2,.... Bei schon besuchten Knoten wird abgebrochen.
WS 2006/2007 Computer Science
Seite 147
Der Algorithmus zum Tiefendurchlauf
Sei |V| = n.
algorithm dfs (v)
// Tiefendurchlauf vom Knoten v aus
if (v wurde noch nicht besucht){
verarbeite v;
markiere v als besucht;
for (jedem Nachfolger vi von v)
dfs (vi)
}
WS 2006/2007 Computer Science
Seite 148
74
Bemerkung zum Algorithmus zum Tiefendurchlauf
•
Ob v bereits besucht wurde, wird in einem zusätzlichem Array mit
boolean-Werten der Länge n vermerkt. Vor Ausführung des
Algorithmus besteht das Array aus false Werten. Falls ein Knoten
besucht wurde, wird die entsprechende Position im Array auf true
gesetzt.
•
Da im allgemeinen nicht alle Knoten von einem Wurzelknoten
erreichbar sind, muss der Algorithmus dfs (v) in folgende Schleife
eingebunden werden:
for (i = 1; i <= n; i++)
dfs(v)
WS 2006/2007 Computer Science
Seite 149
Der Algorithmus zum Breitendurchlauf
algorithm bfs (v)
// Breitendurchlauf vom Knoten v aus
fuege in die leere Schlange q den Knoten v ein;
markiere v als besucht;
while (q enthaelt Elemente){
w ← erste Element von q;
entferne erstes Element aus q;
verarbeite w;
for (jedem Nachfolger wi von w)
if (wi wurde noch nicht besucht){
haenge wi an q an;
markiere wi als besucht;
}
}
WS 2006/2007 Computer Science
Seite 150
75
Bemerkung zum Algorithmus zum Breitendurchlauf
•
Zur Realisierung des Breitendurchlaufs verwendet man die
Datenstruktur ‚Schlange‘ (FiFo).
•
Da im allgemeinen nicht alle Knoten von einem Wurzelknoten
erreichbar sind, muss der Algorithmus bfs (v) in folgende Schleife
eingebunden werden:
for (i = 1; i <= n; i++)
if (v wurde noch nicht besucht)
bfs(v)
WS 2006/2007 Computer Science
Seite 151
Bestimmung kürzester Wege von einem Knoten zu allen anderen
Knoten
Gegeben sei ein gerichteter Graph, dessen Kanten mit positiven reellen
Zahlen (Kosten) beschriftet sind.
Problem: Von einem beliebigen Knoten k (Quelle) finde Kosten des
jeweils billigsten Pfades zu jedem anderen Knoten.
Unter Kosten des Pfades versteht man die Kosten seiner Kanten.
Ein Algorithmus zur Lösung dieses Problems ist der Algorithmus von
Dijkstra.
WS 2006/2007 Computer Science
Seite 152
76
Algorithmus von Dijkstra
Voraussetzungen:
Sei n = |V| die Anzahl der Knoten im Graph.
Sei Ko ein zweidimensionales Array mit reellen Werten:
Ko: array [0…n-1][0…n-1]
Eintrag Ko[i,j] ist Kosten der Kante i->j, falls diese existiert, sonst maxreal.
Bi ist ein array der Länge n mit reellen Werten und enthält die bisher
geringsten Kosten für Pfade von der Quelle zu den Knoten.
WS 2006/2007 Computer Science
Seite 153
algorithm Dijkstra{
M
←
{0};
Bi[0]←0;
for (i = 1; i<= n-1;i++)
Bi[i]
←
Ko[0][i];
//Initialisierung
for (i = 0; i <=n-2; i++){
fuege denjenigen Knoten w
∈ V \ M zu M hinzu,
bei dem Bi[w] minimal ist;
for (alle Knoten v ∈ V \ M )
Bi[v]←min(Bi[v], Bi[w] + Ko[w,v]);
}
}
WS 2006/2007 Computer Science
Seite 154
77
Bemerkung zum Dijkstra-Algorithmus
•
Die Zeitkomplexität beträt O(|V|2).
•
Werden die Bi[v] in einer Prioritätsschlange verwaltet, so beträgt die
Zeitkomplexität O(|E|*log(|V|).
WS 2006/2007 Computer Science
Seite 155
Bestimmung kürzester Wege zwischen allen Paaren von Knoten
Verfahren von Floyd
Idee: In Matrix A werden Kosten des bis jetzt billigsten Pfades von i nach j
für alle i, j ∈ V gespeichert.
Die Zeitkomplexität beträgt O(|V|3).
WS 2006/2007 Computer Science
Seite 156
78
algorithm Floyd{
for (i = 0; i<= n-1;i++)
for (j = 0; j<= n-1;j++)
A[i][j]
← Ko[i][j];
//Initialisierung
for (i = 0; i<= n-1;i++)
A[i][i] ← 0;
for (k = 0; k <=n-1; k++)
for (i = 0; i <=n-1; i++)
for (j= 0; j<=n-1; j++)
if A[i][k] + A [k][j] < A[i][j]
A[i][j]
← A[i][k]
+ A [k][j]
}
WS 2006/2007 Computer Science
Seite 157
Verfahren von Warshall
Der Algorithmus von Warshall gibt an, ob ein Pfad im Graph existiert.
A ist ein boolesche Matrix.
Algorithmus läuft wie bei Floyd, außer innerste Schleife:
for (j= 0; j<=n-1; j++)
if ( A[i][j] = false)
A[i][j] ←(A[i][k] AND A[k][j])
WS 2006/2007 Computer Science
Seite 158
79
Einschub
Die Datenstruktur „Mischwald“.
Unter einem Mischwald versteht man eine Datenstruktur, für die 2
Operationen definiert ist:
•
Vereinigen zweier disjunkter Mengen (diese werden Komponenten
genannt) in Zeit O(1). Diese Operation nennt man merge.
•
Feststellen, zu welcher Menge ein Element gehört in Zeit O(log(n)).
Die Datenstruktur Mischwald ist eine Hilfstruktur für Graphen.
WS 2006/2007 Computer Science
Seite 159
Ungerichtete Graphen
Definitionen
Ein Graph G = (V,E) heißt ungerichteter Graph :
auch (w,v)
⇔ für alle (v,w) ∈ E ist
∈ E.
G‘ = (V‘,E‘) heißt Subgraph von G = (V,E) :
G heißt verbunden :
⇔
V‘ ⊆ V, E‘ ⊆ (V‘ x V‘) ∩ E.
⇔ zu je zwei Knoten x, y existiert ein Pfad x,…,y.
Ein Spannbaum für G ist ein verbundener Subgraph Sp = (V,E‘) von G
ohne Zyklen, wobei E‘ eine Teilmenge von E ist.
WS 2006/2007 Computer Science
Seite 160
80
Sei G = (V,E) verbundener Graph mit Kosten ko[i,j] für alle Kanten
(i,j) ∈ E. Die Kosten eines Spannbaums sind die Summe der Kosten
über alle e ∈ E‘.
Ziel: Zu einem verbundenen Graphen G mit Kantenbewertung wird ein
Spannbaum mit minimalen Kosten gesucht. Diesen nennt man
minimalen Spannbaum.
WS 2006/2007 Computer Science
Seite 161
Eigenschaften minimaler Spannbäume
Lemma:
Sei {U,W} eine Zerlegung der Knotenmenge V für G = (V,E).
Sei (u,w) eine Kante in G mit minimalen Kosten unter allen Kanten
{(u‘,w‘) | u‘ ∈ U, w‘ ∈W}. Dann gibt es einen minimalen Spannbaum für
G, der (u,w) enthält.
WS 2006/2007 Computer Science
Seite 162
81
Algorithmus von Kruskal
Sei G = (V,E) ein verbundener, kantenbewerteter Graph mit n Knoten.
Q sei eine Prioritäts-Schlange mit den Kosten der Kanten, wobei die
geringsten Kosten höchste Priorität haben. Das Entfernen des Minimums
erfolgt mit dem Algorithmus deletemin.
P sei die Datenstruktur Mischwald mit den Operationen find und merge.
Gesucht: Minimaler Spannbaum für den Graphen G.
WS 2006/2007 Computer Science
Seite 163
algorithm Kruskal (G){
Initialisiere
P so, dass jeder Knoten aus V eine eigene
Komponente bildet;
SP
←
(V, O );
//Initialisierung des Spannbaums
Füge alle Kanten aus E bzgl. ihrer Kosten in Q ein;
zaehler ← n;
while (zaehler > 1){
(Q,(v,w))
a
b
← deletemin(Q);
← find(P,v);
← find(P,w);
// zu welcher Komponente gehört v?
// zu welcher Komponente gehört w?
if (a != b){
insert(SP, (v,w)); //fügt Kante (v,w) in Baum SP ein
P ← merge (P, a, b); // mische Komponente a und b
zaehler ← zaehler – 1;
}
}}
WS 2006/2007 Computer Science
Seite 164
82
Bemerkung zum Algorithmus von Kruskal
Die Zeitkomplexität ist O(e log e) , wobei e die Anzahl der Kanten ist.
WS 2006/2007 Computer Science
Seite 165
Teil 2:
Grundlagen der Theoretischen Informatik
Einführung in die Automatentheorie und formale Sprachen
WS 2006/2007 Computer Science
Seite 166
83
Grundbegriffe
Als Alphabet ∑ bezeichnet man eine nicht-leere Menge. Die Elemente
dieser Menge heißen Symbole oder Buchstaben.
Die endlich langen Zeichenfolgen, die über ein Alphabet ∑ gebildet
werden können, heißen Wörter über ∑ .
Für ein gegebenes Alphabet ∑
∗
bezeichnet ∑ die Menge aller
Wörter, die sich durch Hintereinanderschreiben von Symbolen aus ∑
∗
bilden lassen, d.h. ∑ ist die Menge aller endlichen Folgen von
Elementen aus ∑ inkl. der leeren Folge bzw. das leere Wort, das mit ε
bezeichnet wird.
WS 2006/2007 Computer Science
Seite 167
Sei ∑
∗
ein Alphabet. Dann heißt jede Menge L ⊆ ∑
eine (formale)
Sprache über ∑ .
WS 2006/2007 Computer Science
Seite 168
84
Deterministische endliche Automaten und reguläre Sprachen
Definition: Ein deterministischer endlicher (Zustands-) Automat ist ein
System A = ( Σ , S , δ , s 0 , F ) . Dabei ist ∑ das Eingabealphabet und
S die Zustandsmenge von A,
Menge der Endzustände und
s0 ∈ S ist der Startzustand, F ⊆ S die
δ : S ×Σ → S die Zustandsüberführungs-
funktion von A.
A heißt deterministisch, da zu einem Zustand und einem Eingabesymbol
höchstens ein Folgezustand existieren kann.
WS 2006/2007 Computer Science
Seite 169
Sei
A = (Σ , S , δ , s0 , F )
ein endlicher Automat.
Dann wird die erweiterte Zustandsüberführungsfunktion δ ∗ definiert
durch
δ ∗ : S × Σ∗ → S
δ ∗(s,ε ) = s
mit
für alle
s∈S
δ ∗ (s, a w) = δ ∗ (δ (s, a),w) , a ∈Σ, w∈Σ∗
WS 2006/2007 Computer Science
Seite 170
85
Konfiguration und Konfigurationsübergänge
Eine Konfiguration kA eines Automaten A beschreibt den aktuellen
Stand der Verarbeitung einer Eingabefolge von A. Eine Konfiguration
kann durch ein Paar k = kA = (s,v) mit
s∈S
und
v ∈ Σ∗
beschrieben werden.
Ein Konfigurationsübergang von einer Konfiguration k = (s,aw) zu einer
Konfiguration k‘ = (s‘,w) kann stattfinden, falls der Zustandsübergang
δ (s, a) = s' existiert, wobei s , s '∈ S , w ∈ Σ ∗ , a ∈ Σ.
Ein Konfigurationsübergang von k = (s,w) zu k‘ = (s‘,w‘) wird durch
(s,w)
(s‘,w‘) dargestellt.
WS 2006/2007 Computer Science
Seite 171
Reguläre Sprachen
Definition:
Sei A = ( Σ , S , δ , s 0 , F ) ein endlicher Automat. Dann heißt die
Sprache
L ( A) = {w ∈ Σ ∗ ( s0 , w)
∗
( s , ε ), s ∈ F }
die von A akzeptierte Sprache.
* bezeichnet die reflexiv-transitive Hülle der Relation
Eine Sprache L ⊆ Σ ∗ heißt regulär, falls es einen endlichen
Automaten A gibt, der L akzeptiert, d.h. für den L = L(A) gilt.
WS 2006/2007 Computer Science
Seite 172
86
Zusammenfassung
•
In Abhängigkeit ihres aktuellen Zustandes und einer Eingabe gehen
endliche Automaten gemäß einer festgelegten deterministischen
Zustandsüberführung in einen neuen Zustand über.
•
Die Abarbeitung eines Eingabewortes geschieht durch einen
Prozess, der durch eine Folge von Konfigurationsübergängen
formal beschrieben werden kann.
•
Ein Automat akzeptiert das Eingabewort, wenn er nach seiner
vollständigen Abarbeitung einen Endzustand erreicht hat.
•
Die Menge aller von einem endlichen Automaten akzeptierten
Wörtern stellt die von ihm akzeptierte Sprache dar.
•
Von endlichen Automaten akzeptierte Sprachen heißen reguläre
Sprachen.
WS 2006/2007 Computer Science
Seite 173
Nichtdeterministische endliche Automaten
Definition:
Ein nichtdeterministischer endlicher Automat ist ein System
A = ( Σ , S , δ , S 0 , F ) . Dabei ist ∑ das Eingabealphabet und S die
Zustandsmenge von A,
S0 ⊆ S
ist die Menge der Startzustände,
F ⊆ S die Menge der Endzustände und δ ⊆ S ×Σ× S
die
Zustandsüberführungsrelation von A.
δ
ist ein Menge von Tripeln (Zustand, Eingabesymbol, Folgezustand)
WS 2006/2007 Computer Science
Seite 174
87
Ein Konfigurationsübergang von k = (s,aw) zu einer k‘ = (s‘,w), d.h.
(s,aw)
(s‘,w‘) kann stattfinden, falls (s,a,s‘) ∈ δ ,
a ∈ Σ, w ∈ Σ ∗
Die von einem nichtdeterministischen Automaten A akzeptierte
Sprache L(A) wird definiert durch
L ( A) = {w ∈ Σ ∗ ( s 0 , w)
∗
( s , ε ), s0 ∈ S 0 , s ∈ F }
WS 2006/2007 Computer Science
Seite 175
Zusammenfassung
•
Nichtdeterministische endliche Automaten lassen in einem Zustand
für eine Eingabe mehrere Folgezustände zu.
•
Zur Überprüfung der Akzeptanz von Eingabeworten, kann bei
sequentieller Abarbeitung das sog. Backtracking nötig sein.
•
Die parallele Abarbeitung eines Wortes führt alle möglichen
Konfigurationsfolgen gleichzeitig aus.
•
Nichtdeterministische und deterministische endliche Automaten
akzeptieren dieselbe Klasse von Sprachen, dies ist die Klasse der
regulären Sprachen.
WS 2006/2007 Computer Science
Seite 176
88
Grammatiken
Ein endlicher Automat definiert die Sprache durch Akzeptieren ihrer
Wörter.
Mit Hilfe von Grammatiken werden Wörter einer Sprache erzeugt.
Grammatiken geben Regeln an, mit denen aus einem Startwert alle
Wörter der Sprache hergeleitet werden können
Zunächst betrachten wir Typ-3 Grammatiken.
WS 2006/2007 Computer Science
Seite 177
Typ-3 Grammatiken: Rechtslineare- und linkslineare
Grammatiken
Definition:
Eine rechtslineare Grammatik G = ( Σ , N , P , S ) über ∑ besteht
aus dem Terminalalphabet ∑ , dem davon disjunkten
Nonterminalalphabet N, einer endlichen Relation
sowie dem Startsymbol
Die Elemente p = (l,r)
s ∈ N.
P ⊆ N ×(Σ N ∪Σ ∪{ε})
∈ P heißen Produktion oder Regeln, P heißt die
Produktionenmenge. Man schreibt für (l,r)
l →r
WS 2006/2007 Computer Science
Seite 178
89
Ein Ableitungsschritt mit der rechtslinearen Grammatik G = ( Σ , N , P , S )
ist eine Relation definiert durch
u A ⇒ u w genau dann, wenn A → w ∈ P , wobei
u ∈Σ∗, A∈ N, w∈Σ N ∪Σ ∪{ε }.
Eine Ableitung in G läßt sich formalisieren durch die reflexiv transitive
Hülle ⇒ ∗ von ⇒ .
WS 2006/2007 Computer Science
Seite 179
Die von G erzeugte Sprache L(G) ist definiert durch
{
}
L (G ) = w ∈ Σ ∗ S ⇒ ∗ w
Zwei Grammatiken G1 und G2 heißen äquivalent, falls sie dieselbe
Sprache erzeugen, d.h. falls L(G1) = L(G2) gilt.
Eine Sprache über L ⊆ Σ∗
heißt rechtslinear, falls eine rechtslineare
Grammatik G über ∑ existiert mit L = L(G).
WS 2006/2007 Computer Science
Seite 180
90
Definition:
Eine linksslineare Grammatik G = ( Σ , N , P , S ) über ∑ besteht
aus dem Terminalalphabet ∑ , dem davon disjunkten
Nonterminalalphabet N, einer endlichen Relation
sowie dem Startsymbol
s ∈ N.
P ⊆ N ×(N Σ ∪Σ ∪{ε})
Ein Ableitungsschritt mit der linkslinearen Grammatik
ist eine Relation definiert durch
Au ⇒ wu
genau dann, wenn
A → w∈ P
, wobei
u ∈Σ∗, A∈ N, w∈ N Σ ∪Σ ∪{ε}.
WS 2006/2007 Computer Science
Seite 181
Satz: Zu jeder rechtslinearen Grammatik über ∑ existiert eine
äquivalente linklineare Grammatik.
Zu jeder linkslinearen Grammatik über ∑ existiert eine äquivalente
rechtslineare Grammatik.
WS 2006/2007 Computer Science
Seite 182
91
Äquivalenz von endlichen Automaten und Typ-3 Grammatiken
Satz:
Zu jeder Typ-3 Grammatik G über dem Alphabet ∑ existiert ein
endlicher Automat A über ∑ mit L(G) = L(A).
Zu jedem endlichen Automaten A über dem Alphabet ∑ existiert eine
rechtslineare Grammatik G über ∑ mit L(A) = L(G).
WS 2006/2007 Computer Science
Seite 183
Zusammenfassung
•
Typ-3 Grammatiken, d.h. rechtslineare und linkslineare
Grammatiken erzeugen Wörter, ausgehend von einem Startsymbol,
mit Hilfe von Ersetzungsregeln. Dies geschieht buchstabenweise
von links nach rechts bzw. von rechts nach links.
•
Rechtslineare und linkslineare Grammatiken sind untereinander
äquivalente erzeugende Konzepte für reguläre Sprachen.
•
Sie sind äquivalent zu endlichen Automaten.
WS 2006/2007 Computer Science
Seite 184
92
Endliche Maschinen
Ein endlicher Automat akzeptiert eine reguläre Sprache, erzeugt aber
keine Ausgabe.
Endliche Automaten mit einer Ausgabefunktion bezeichnet man als
endliche Maschinen.
Zwei Vertreter der endlichen Maschinen sind die sog. Moore- und
Mealy-Maschinen.
WS 2006/2007 Computer Science
Seite 185
Mealy-Machinen
Definition:
Eine Mealy-Maschine M = ( Σ , ∆ , S , δ , λ , s 0 ) besteht aus dem
Eingabealphabet Σ , dem Ausgabealphabet ∆ , der endlichen
Zustandsmenge S , der Zustandsüberführungsfunktion δ : S × Σ → S,
der Ausgabefunktion λ : S × Σ → ∆ und den Startzustand s ∈ S 0 .
Definition:
Eine Moore-Maschine M = ( Σ , ∆ , S , δ , λ , s 0 ) besteht aus dem
Eingabealphabet Σ , dem Ausgabealphabet ∆ , der endlichen
Zustandsmenge S , der Zustandsüberführungsfunktion δ : S × Σ → S ,
der Ausgabefunktion λ : S → ∆
und den Startzustand s ∈ S 0 .
WS 2006/2007 Computer Science
Seite 186
93
Typ-2 Grammatiken: Kontextfreie Grammatiken
Nichtreguläre Sprachen können durch Typ-3 Grammatiken nicht
erzeugt werden. Hierzu benötigt man Kontextfreie Grammatiken
Definition:
Eine Grammatik G = ( Σ , N , P , S ) mit dem Terminalalphabet ∑ ,
dem davon disjunkten Nichtterminalalphabet N, der endlichen
Produktionsmenge P und dem Startsymbol
über ∑ , falls
s∈N
heißt kontextfrei
P ⊆ N × (Σ ∪ N)∗
WS 2006/2007 Computer Science
Seite 187
Eine Sprache L heißt kontextfrei über ∑ , falls es eine kontextfreie
Grammatik G über ∑ mit L = L(G) gibt.
Kontextfreie Grammatiken und Sprachen heißen auch Typ-2
Grammatiken bzw. Typ-2 Sprachen.
Jede Typ-3 Grammatik ist kontextfrei.
Die Klasse der regulären Sprachen über einem Alphabet ∑ ist eine
Teilklasse der Klasse der kontextfreien Sprachen über ∑
.
WS 2006/2007 Computer Science
Seite 188
94
Kellerautomaten
Typ-3 Grammatiken sind äquivalent zu endlichen Automaten.
Nun suchen wir Automaten, die äquivalent zu kontextfreien
Grammatiken sind. Dies sind die Kellerautomaten.
Definition:
Ein nichtdeterministischer Kellerautomat ist ein System
mit
dem
Eingabe
K
= (Σ
, S , Γ, δ , s0 , ⊥, F ) mit dem Eingabealphabet Σ, der endlichen
Zustandsmenge S , dem Kelleralphabet Γ , der Zustandsüberführung
∗
δder
: SZustandsüberführungsfu,
× (Σ ∪ {ε }) × Γ → 2S ×Γ dem Startzustand s0 ∈ S , dem KellerBottomsymbol ⊥∈ Γ und der Endzustandsmenge F ⊆ S. .
WS 2006/2007 Computer Science
Seite 189
95
Herunterladen