Präsentation - Torsten Finke
Präsentation - Torsten Finke Präsentation - Torsten Finke
Überblick Ankündigungen Algorithmen (Revision 183) Prof. Dr.-Ing. Torsten Finke FOM 2013-12-01 Einführung Datenstrukturen Algorithmen – Konzepte und Analyse Sortieren Zeichenketten Kompression Kryptologie Geometrie Graphen Prof. Dr.-Ing. Torsten Finke (FOM) Algorithmen 2013-12-01 1 / 235 Prof. Dr.-Ing. Torsten Finke (FOM) Algorithmen 2013-12-01 2 / 235 Ankündigungen Inhalte Ankündigungen Klausur Algorithmen – Folien Klausur http://www.dr-torsten-finke.de/lehre/algorithmen/bachelor/algorithmen.pdf http://www.dr-torsten-finke.de/lehre/algorithmen/bachelor/algorithmen-print.pdf ◮ Formalia ◮ Dauer 120 Minuten ◮ keine Hilfsmittel ◮ Formvorschriften ◮ Inhalt ◮ Inhalt komplett relevant ◮ kein Repetitorium ◮ Auswahlklausur ◮ Schwerpunkt auf Verständnis Prof. Dr.-Ing. Torsten Finke (FOM) Algorithmen 2013-12-01 3 / 235 Prof. Dr.-Ing. Torsten Finke (FOM) Algorithmen 2013-12-01 4 / 235
- Seite 2 und 3: Algorithmik - Literatur Ankündigun
- Seite 4 und 5: Einführung Beispiel - ggT Einführ
- Seite 6 und 7: Datenstrukturen Elementare Datenstr
- Seite 8 und 9: Datenstrukturen Lineare Datenstrukt
- Seite 10 und 11: Datenstrukturen Lineare Datenstrukt
- Seite 12 und 13: Datenstrukturen Bäume Datenstruktu
- Seite 14 und 15: Datenstrukturen Knoten löschen - e
- Seite 16 und 17: Algorithmen - Konzepte und Analyse
- Seite 18 und 19: Algorithmen - Konzepte und Analyse
- Seite 20 und 21: Sortieren Insertion Sort Sortieren
- Seite 22 und 23: Sortieren Merge Sort Sortieren Merg
- Seite 24 und 25: Sortieren Heap Sort Sortieren Heap
- Seite 26 und 27: Sortieren Heap Sort Zeichenketten S
- Seite 28 und 29: Zeichenketten Suchen in Zeichenkett
- Seite 30 und 31: Zeichenketten Suchen in Zeichenkett
- Seite 32 und 33: Zeichenketten Rabin Karp - Implemen
- Seite 34 und 35: Kompression Lauflängenkompression
- Seite 36 und 37: Kompression Huffman-Kompression Kom
- Seite 38 und 39: Kompression Huffman-Kompression Kom
- Seite 40 und 41: DCT - Kompression Kompression Verlu
- Seite 42 und 43: Kryptologie Verschlüsselung und Pr
- Seite 44 und 45: Diskurs: Modulorechnung Kryptologie
- Seite 46 und 47: Kryptologie Kryptologie - Anwendung
- Seite 48 und 49: Geometrie Einfacher geschlossener P
- Seite 50 und 51: Geometrie Polygon Geometrie Polygon
Überblick<br />
Ankündigungen<br />
Algorithmen<br />
(Revision 183)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong><br />
FOM<br />
2013-12-01<br />
Einführung<br />
Datenstrukturen<br />
Algorithmen – Konzepte und Analyse<br />
Sortieren<br />
Zeichenketten<br />
Kompression<br />
Kryptologie<br />
Geometrie<br />
Graphen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 1 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 2 / 235<br />
Ankündigungen<br />
Inhalte<br />
Ankündigungen<br />
Klausur<br />
Algorithmen – Folien<br />
Klausur<br />
http://www.dr-torsten-finke.de/lehre/algorithmen/bachelor/algorithmen.pdf<br />
http://www.dr-torsten-finke.de/lehre/algorithmen/bachelor/algorithmen-print.pdf<br />
◮ Formalia<br />
◮ Dauer 120 Minuten<br />
◮ keine Hilfsmittel<br />
◮ Formvorschriften<br />
◮ Inhalt<br />
◮ Inhalt komplett relevant<br />
◮ kein Repetitorium<br />
◮ Auswahlklausur<br />
◮ Schwerpunkt auf Verständnis<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 3 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 4 / 235
Algorithmik – Literatur<br />
Ankündigungen<br />
Literatur<br />
Arndt, Jörg: Matters Computational – Ideas, Algorithms, Source Code.<br />
Autor, 2010.<br />
http://www.jjj.de/fxt/.<br />
Cormen, Thomas H., Charles E. Leiserson und Ronald L. Rivest:<br />
Introduction to Algorithms.<br />
The MIT Press, 3. Auflage, 2009.<br />
ISBN: 978-0262533058.<br />
Engeln-Müllges, Giesela und Frank Uhlig: Numerical Algorithms with C.<br />
Springer-Verlag, 1997.<br />
ISBN: 3540605304.<br />
Knuth, Donald E.: The Art of Computer Programming – Fascicles 0–4.<br />
Addison-Wesley, 2009.<br />
ISBN: 978-0321637130.<br />
Sedgewick, Robert: Algorithms in C.<br />
Addison-Wesley, 1990.<br />
ISBN: 978-0201514254.<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 5 / 235<br />
Algorithmik – Quelltexte<br />
Ankündigungen<br />
Literatur<br />
◮ Quelltexte sind weitgehend in Anlehnung an [Sed90] wiedergegeben.<br />
◮ Die dargestellten Programme dienen primär der Illustration der<br />
diskutierten Algorithmen. Korrekte Funktion und praktische<br />
Verwendbarkeit sind ausdrücklich nicht garantiert.<br />
◮ Die Beispiele sollen Anregungen zu eigenen Programmierübungen in<br />
beliebigen Programmiersprachen sein.<br />
◮ Programmbeispiele sind herzlich willkommen – bitte einsenden mit<br />
Angaben zur Urheberschaft und einer Lizenz (MIT, BSD, GPL etc.)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 6 / 235<br />
Einführung<br />
Begriffe<br />
Einführung<br />
Programmcodes – C<br />
Begriffe<br />
Programmcodes – C<br />
◮ Al Chwarizmi – Algorithmus<br />
◮ Verarbeitungsvorschrift (finit, determiniert(?))<br />
◮ Darstellung:<br />
◮ Programmablaufplan (DIN 66001/ISO 5807)<br />
◮ Struktogramm (Nassi/Shneidermann, DIN 66261)<br />
◮ Pseudocode<br />
◮ maschinennah, Rechenaufwand gut bestimmbar<br />
◮ Typen: int, char, double<br />
◮ globale Variable (kompakter Code)<br />
◮ Felder: Zeiger auf erstes Element, Länge separat<br />
◮ Strukturen: struct entry { int x, y; }<br />
◮ Pointer: struct entry *p; ...; a = p->x;<br />
◮ Kontrollstrukturen<br />
◮ Operatoren<br />
◮ Ein-/Ausgabe: c = getchar(); printf("n = %d\n", n)<br />
◮ Zip-Archiv<br />
◮ andere Programmiersprachen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 7 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 8 / 235
Einführung<br />
Größter gemeinsamer Teiler<br />
Beispiel – ggT<br />
Einführung<br />
ggT – Idee: Primfaktorzerlegung<br />
Beispiel – ggT<br />
◮ ggT(84, 231)<br />
Beispiel:<br />
◮ ggT(84, 231) =?<br />
◮ Idee?<br />
84 = 2 · 2 · 3 · 7<br />
231 = 3 · 7 · 11<br />
⇒ ggT(84, 231) = 3 · 7<br />
= 21.<br />
◮ Erforderlich:<br />
◮ Primzahlenverzeichnis<br />
◮ Listen für Faktoren<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 9 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 10 / 235<br />
Einführung<br />
Beispiel – ggT<br />
Primzahlen – Sieb des Eratosthenes<br />
Einführung<br />
Beispiel – ggT<br />
Sieb des Eratosthenes – Implementation<br />
2 3 4 5 6 7 8 9 10 11 12<br />
13 14 15 16 17 18 19 20 21 22 23 24<br />
25 26 27 28 29 30 31 32 33 34 35 36<br />
37 38 39 40 41 42 43 44 45 46 47 48<br />
49 50 51 52 53 54 55 56 57 58 59 60<br />
61 62 63 64 65 66 67 68 69 70 71 72<br />
73 74 75 76 77 78 79 80 81 82 83 84<br />
85 86 87 88 89 90 91 92 93 94 95 96<br />
97 98 99 100 101 102 103 104 105 106 107 108<br />
109 110 111 112 113 114 115 116 117 118 119 120<br />
121 122 123 124 125 126 127 128 129 130 131 132<br />
eratos(int s[], int n)<br />
{<br />
int i, k;<br />
/* prepare sieve: 1 - prime, 0 - no prime */<br />
for ( s[1] = 0, i = 2; i
Einführung<br />
Beispiel – ggT<br />
Einführung<br />
Beispiel – ggT<br />
Euklid – ggT: Idee<br />
Fläche: 30 × 21 – maximale Kachelgröße?<br />
Euklid – ggT: Pseudo-Code<br />
1: procedure gcd(u, v)<br />
2: while u > 0 do<br />
3: if u < v then<br />
4: (u, v) ← (v, u) ⊲ let u always be the greater value<br />
5: end if<br />
6: u ← u − v ⊲ try mod<br />
7: end while<br />
8: return v ⊲ gcd is v<br />
9: end procedure<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 13 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 14 / 235<br />
Einführung<br />
Beispiel – ggT<br />
Einführung<br />
Beispiel – ggT<br />
Euklid – ggT: Beispiel<br />
Euklid – ggT: Programmablaufplan<br />
◮ ggT(84, 231) =?, ggT(233, 144) =?<br />
◮ 231<br />
84<br />
147<br />
84<br />
63<br />
21<br />
42<br />
21<br />
21 ⇒ ggT(84, 231) = 21<br />
0<br />
233<br />
144<br />
89<br />
55<br />
34<br />
21<br />
13<br />
8<br />
5<br />
3<br />
2<br />
1<br />
1 ⇒ ggT(233, 144) = 1<br />
0<br />
n<br />
Start<br />
read(u,v)<br />
u,v > 0?<br />
j<br />
n<br />
u > 0?<br />
j<br />
n<br />
u < v?<br />
j<br />
(u,v) := (v, u)<br />
u := u − v<br />
print(v)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 15 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 16 / 235
Einführung<br />
Beispiel – ggT<br />
Einführung<br />
Beispiel – ggT<br />
Euklid – ggT: Struktogramm<br />
Euklid – ggT: Implementation<br />
Loop:<br />
Input: u, v<br />
j<br />
u, v > 0<br />
while: u > 0<br />
j<br />
u < v<br />
n<br />
(u,v) := (v,u)<br />
u := u − v<br />
Output: v<br />
n<br />
int gcd(int u, int v)<br />
{<br />
int t;<br />
while (u > 0) {<br />
if (u < v) {<br />
t = u; u = v; v = t;<br />
}<br />
u = u - v;<br />
}<br />
return v;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 17 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 18 / 235<br />
Einführung<br />
Beispiel – ggT<br />
Einführung<br />
Beispiel – ggT<br />
Euklid – Fazit<br />
Übungen<br />
◮ einfache Methode<br />
◮ einfache Operationen (Addition, Subtraktion, Vergleich)<br />
◮ einfache Datentypen<br />
◮ Beschreiben Sie die behandelten Algorithmen so, dass ein Mensch sie<br />
ausführen kann! Testen Sie Ihre Beschreibung mit einer<br />
Versuchsperson!<br />
◮ Implementieren Sie die dargestellten Algorithmen in einer<br />
Programmiersprache Ihrer Wahl!<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 19 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 20 / 235
Datenstrukturen<br />
Elementare Datenstrukturen<br />
Datenstrukturen<br />
Speicherzellen und Felder<br />
Elementare Datenstrukturen<br />
Speicherzellen und Felder<br />
◮ einfache Datenstrukturen<br />
◮ Ganzzahl – int (long int, unsigned int)<br />
◮ Fließpunkt – float, double<br />
◮ Zeichen(-kette) – char<br />
◮ aggregierte Datenstrukturen<br />
◮<br />
◮<br />
Feld<br />
Struktur<br />
◮ Arrays<br />
◮ Matrizen<br />
◮ Indizes (effizientes Vertauschen)<br />
Index i[n] Array a[m][n]<br />
/* swap rows p, q by index */<br />
t = i[p];<br />
i[p] = i[q];<br />
i[q] = t;<br />
/* now access first element */<br />
x = a[i[p]][0];<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 21 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 22 / 235<br />
Datenstrukturen<br />
Speicherzellen und Felder<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Feld – Operationen<br />
Liste<br />
◮ n Elemente – Problemumfang<br />
◮ Aufwand A = A(n)<br />
◮ Einfügen an gegebener Position<br />
◮ Aufbau<br />
Head<br />
Value<br />
ptr<br />
Node<br />
Value<br />
ptr<br />
Value<br />
ptr<br />
Tail<br />
A insert = O(n).<br />
◮ Löschen an gegebener Position: A remove = O(n).<br />
◮ Suchen<br />
◮<br />
◮<br />
günstigster Fall: A = O(1)<br />
ungünstigster Fall: A = O(n)<br />
◮<br />
◮<br />
◮<br />
◮<br />
Kopf<br />
Knoten<br />
Ende<br />
doppelte Verkettung<br />
◮ Funktionen<br />
◮ Initialisierung<br />
◮ Einfügen<br />
◮ Löschen<br />
◮ Traversieren(Suchen/Modifizieren)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 23 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 24 / 235
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Liste – Implementation/Initialisierung<br />
Liste – Element einfügen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
struct node {<br />
int key;<br />
struct node *next;<br />
};<br />
struct node *head, *z, *t;<br />
void listinitialize()<br />
{<br />
head = malloc(sizeof *head); /* get memory from OS */<br />
z = malloc(sizeof *z);<br />
head->next = z;<br />
z->next = z;<br />
}<br />
struct node *insertafter(int v, struct node *n)<br />
{<br />
struct node *x;<br />
x = (struct node *) malloc(sizeof *x);<br />
x->key = v; /* 1. insert value */<br />
x->next = n->next; /* 2. connect successor */<br />
n->next = x; /* 3. connect predecessor - why last? */<br />
return x;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 25 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 26 / 235<br />
Liste – Element löschen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
void deletenext(struct node *n)<br />
{<br />
t = n->next;<br />
n->next = n->next->next; /* memory leak */<br />
free(t); /* release memory */if ( t != z ) free(t);<br />
}<br />
Datenstrukturen<br />
Liste traversieren – Element suchen<br />
◮ Suche bis Listenende<br />
Lineare Datenstrukturen<br />
struct node *search(int v, struct node *n) {<br />
while ( n != n->next ) { /* until end of list */<br />
if ( n->key == v ) break; /* found */<br />
n = n->next; /* otherwise continue */<br />
}<br />
return n;<br />
}<br />
◮ Suche bis Sentinel<br />
struct node *search(int v, struct node *n) {<br />
z->key = v; /* sentinel */<br />
while ( n->key != v ) n = n->next; /* will find */<br />
return n;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 27 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 28 / 235
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Listen – Übungen<br />
Stack/Stapel<br />
◮ LiFo<br />
push<br />
pop<br />
◮ Implementation Modifizieren<br />
◮ Aufwand der Suche nach einem Element?<br />
◮ Optimierungsstrategie für die Suche?<br />
Stackpointer<br />
◮ Stackpointer<br />
◮ Operationen<br />
◮ Initialisierung<br />
◮ Push<br />
◮ Pop<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 29 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 30 / 235<br />
Datenstrukturen<br />
Stack – Implementation/Aufbau<br />
struct node {<br />
int key;<br />
struct node *next;<br />
};<br />
Lineare Datenstrukturen<br />
static struct node *head, *z, *t;<br />
stackinit() {<br />
head = (struct node *) malloc(sizeof *head);<br />
z = (struct node *) malloc(sizeof *z);<br />
head->next = z;<br />
z->next = z; head->key = z->key = 0;<br />
}<br />
Datenstrukturen<br />
Stack – Implementation/Operation<br />
Lineare Datenstrukturen<br />
push(int v) {<br />
t = (struct node *) malloc(sizeof *t);<br />
t->key = v; t->next = head->next;<br />
head->next = t;<br />
}<br />
int pop() {<br />
int x;<br />
t = head->next; head->next = t->next;<br />
x = t->key;<br />
if ( ! stackempty() ) free(t);<br />
return x;<br />
}<br />
int stackempty() {<br />
return head->next == z;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 31 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 32 / 235
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Stack – Anwendung: UPN (̷Lukasiewicz)<br />
int b = 10, c, n, t, x;<br />
stackinit();<br />
do {<br />
x = n = 0; /* prepare to read number */<br />
for (c=getchar(); c>=’0’ && c 0) { push(x); /* got number */ }<br />
if (c == ’+’) { push(pop() + pop()); }<br />
else if (c == ’-’) { t = pop(); push(pop() - t); }<br />
else if (c == ’~’) { push(-pop()); }<br />
else if (c == ’*’) { push(pop() * pop()); }<br />
else if (c == ’/’) { if (t = pop()) push(pop()/t); }<br />
} while ( c != EOF )<br />
printf("%d\n", pop());<br />
Queue(Schlange)<br />
◮ FiFo<br />
get<br />
◮ Operationen an beiden Enden:<br />
◮<br />
◮<br />
Put<br />
Get<br />
Datenstrukturen Lineare Datenstrukturen<br />
◮ Anwendung: Schieberegister, Warteschlange<br />
put<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 33 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 34 / 235<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Ringspeicher<br />
Lineare Datenstrukturen – Übung<br />
Head<br />
◮ Implementieren Sie einen Stack mit einem Array!<br />
◮ Implementieren Sie die Funktionen get und put für eine Queue!<br />
◮ Implementieren Sie sinnvolle Funktionen zum Aufbau und zur<br />
Anwendung von Ringspeichern!<br />
◮ Implementieren Sie einen Infix-Parser (Hinweis: Shunting Yard<br />
Algorithmus)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 35 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 36 / 235
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Hash<br />
Hash – Beispiel<br />
◮ Hash-Funktion: z.B. modulo<br />
h(k) = k mod M<br />
◮ k komplex (große Zahl): Stellensystem (Basis b)<br />
k =<br />
◮ Modulo-Rechnung:<br />
n∑<br />
k i b i<br />
(a + b) mod M = (a mod M + b mod M) mod M<br />
(a · b) mod M = (a mod M · b mod M) mod M<br />
◮ Horner-Schema (mit impliziter Modulorechnung)<br />
i=0<br />
Hashkodes zum schnellen Finden von Schlüssel/Wert-Paaren<br />
◮ gegeben: Schlüssel k (kompliziert)<br />
◮ berechne h(k) (eventuell nicht eindeutig)<br />
◮ Aufwand der Suche A = O(1)<br />
◮ verwende h(k) als Index in einem Feld<br />
◮ jeder Feldeintrag ist ein Listenkopf<br />
◮ jede Liste enthält alle Schlüssel gleicher Hashcodes<br />
◮ Knoten tragen komplette Schlüssel und Verweise auf Werte<br />
◮ Vorteil: kurze Listen, effiziente Suche<br />
a 3 x 3 + a 2 x 2 + a 1 x + a 0 = ((a 3 x + a 2 ) · x + a 1 ) · x + a 0<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 37 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 38 / 235<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Hashing – Schlüssel/Wert-Verwaltung<br />
k<br />
h(k)<br />
h(k 1 )<br />
k 1<br />
v 2 v’ 2<br />
h(k 2 )<br />
k2<br />
k’ 2<br />
v 3<br />
h(k 3 )<br />
k 3<br />
M Einträge<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 39 / 235<br />
v 1<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Hash – Wörter zählen: Initialisierung<br />
int M = 101; /* chose prime */<br />
struct node {<br />
char *key; int val;<br />
struct node *next;<br />
} **heads, *z;<br />
unsigned hash(char *k) {<br />
for (int h=0; *k!=’\0’; k++) h=((hnext = z;<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 40 / 235
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Hash – Wörter zählen: eintragen und finden<br />
Hash – Anwendung<br />
void hashinsert(char *k, int h, int v) {<br />
struct node *new = malloc(sizeof *z);<br />
new->key = k; new->val = v;<br />
new->next = heads[h]->next;<br />
heads[h]->next = new;<br />
}<br />
struct node *hashfind(char *k, int h, int *v)<br />
{<br />
struct node *t = heads[h];<br />
z->key = k;<br />
do {<br />
t = t->next;<br />
} while ( strcmp(t->key, k) );<br />
*v = t->val;<br />
return t;<br />
}<br />
◮ sinnvolle Wahl der Hashgröße<br />
◮ Modul M prim<br />
◮ Objekte mit gleichem Hashcode: Listen<br />
◮ Identität:<br />
◮ Hashcodes verschieden: Objekte verschieden<br />
◮ Hashcodes gleich: Objekte möglicherweise gleich<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 41 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 42 / 235<br />
Datenstrukturen<br />
Lineare Datenstrukturen<br />
Datenstrukturen<br />
Bäume<br />
Hash – Übung<br />
Bäume – Aufbau<br />
Wurzel<br />
◮ Zeigen Sie, dass die Modulorechnung distributiv hinsichtlich Addition<br />
und Multiplikation ist!<br />
◮ Gegeben: Kodierungstabelle: A – 1, B – 2, C – 3, ... Z – 26<br />
b = 30, M = 97<br />
Gesucht: Hashcode der Zeichenkette ALGORITHMUS<br />
◮ Implementieren Sie ein Programm, das die vorstehende Aufgabe löst.<br />
Kante<br />
Knoten<br />
Blatt<br />
Pfad<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 43 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 44 / 235
Datenstrukturen<br />
Bäume<br />
Datenstrukturen<br />
Bäume<br />
Binär-Bäume<br />
Verzeichnis-Bäume<br />
n Knoten<br />
Tiefe t<br />
n = 2 t − 1<br />
t = log 2 (n + 1)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 45 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 46 / 235<br />
Datenstrukturen<br />
Bäume<br />
Datenstrukturen<br />
Bäume<br />
Bäume – Traversierung<br />
Suche im Baum<br />
*<br />
M<br />
+ -<br />
H<br />
T<br />
3 4 7 2<br />
D K P W<br />
◮ Pre-Order: (* (+ 3 4) (- 7 2))<br />
◮ In-Order: ((3 + 4) * (7 - 2))<br />
◮ Post-Order: 3, 4 + 7, 2 - *<br />
◮ Level-Order: * + - 3 4 7 2<br />
B F I L<br />
A C E G<br />
N R U Y<br />
Q S X Z<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 47 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 48 / 235
Datenstrukturen<br />
Bäume<br />
Datenstrukturen<br />
Bäume<br />
Binäre Such-Bäume<br />
◮ Sortiertes Einfügen<br />
◮ Suche: A = O(log n)<br />
A<br />
100<br />
80<br />
60<br />
40<br />
20<br />
0<br />
O(n)<br />
O(log n)<br />
10 20 30 40 50 60 70 80 90 100<br />
n<br />
Baum-Implementation: Aufbau<br />
static struct node {<br />
int key, info;<br />
struct node *l, *r;<br />
};<br />
static struct node *t, *head, *z;<br />
treeinitialize()<br />
{<br />
z = (struct node *) malloc(sizeof *z);<br />
z->l = z;<br />
z->r = z;<br />
z->info = -1;<br />
head = (struct node *) malloc(sizeof *head);<br />
head->r = z;<br />
head->key = 0;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 49 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 50 / 235<br />
Datenstrukturen<br />
Bäume<br />
Datenstrukturen<br />
Bäume<br />
Baum-Implementation: Suchen und Ausgeben<br />
int treesearch(int v)<br />
{<br />
struct node *x = head->r;<br />
z->key = v; /* sentinel */<br />
while (v != x->key)<br />
x = (v < x->key) ? x->l : x->r;<br />
return x->info;<br />
}<br />
treeprint(struct node *x)<br />
{<br />
if (x != z) {<br />
treeprint(x->l);<br />
printnode(x); /* visit In-Order */<br />
treeprint(x->r);<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 51 / 235<br />
Baum-Implementation: Einfügen<br />
treeinsert(int v, int info)<br />
{<br />
struct node *p, *x;<br />
p = head;<br />
x = head->r;<br />
while (x != z) {<br />
p = x; x = (v < x->key) ? x->l : x->r;<br />
}<br />
x = (struct node *) malloc(sizeof *x);<br />
x->key = v;<br />
x->info = info;<br />
x->l = x->r = z;<br />
if (v < p->key) p->l = x;<br />
else p->r = x;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 52 / 235
Datenstrukturen<br />
Knoten löschen – einfache Fälle<br />
Bäume<br />
Datenstrukturen<br />
Bäume<br />
Knoten löschen – komplizierter Fall<br />
A<br />
ein NF<br />
C<br />
E<br />
H<br />
NF ohne NF<br />
N<br />
R<br />
S<br />
kein NF<br />
C<br />
E<br />
H<br />
R<br />
P<br />
A<br />
C<br />
E<br />
H<br />
re. NF(E)<br />
N<br />
R<br />
A<br />
C<br />
H<br />
N<br />
R<br />
M<br />
P<br />
M<br />
M<br />
P<br />
M<br />
P<br />
L<br />
L<br />
L<br />
L<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 53 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 54 / 235<br />
Datenstrukturen<br />
Baum-Implementation: Löschen<br />
Bäume<br />
treedelete(int v) {<br />
struct node *c, *p, *x;<br />
z->key = v; p = head; x = head->r;<br />
while (v != x->key) { /* search node */<br />
p = x; x = (v < x->key) ? x->l : x->r;}<br />
t = x; /* t to be deleted */<br />
if (t->r == z) x = x->l; /* node is leaf, cut off */<br />
else if (t->r->l == z) { /* node’s child is leaf */<br />
x = x->r; x->l = t->l;}<br />
else { c = x->r;<br />
while (c->l->l != z) c = c->l; /* substitute */<br />
x = c->l; c->l = x->r;<br />
x->l = t->l; x->r = t->r;}<br />
if (v < p->key) p->l = x;<br />
else p->r = x;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 55 / 235<br />
Datenstrukturen Bäume<br />
Baum-Implementation: Operationen<br />
◮ Suchen: effizient<br />
◮ Einfügen: nach erfolgloser Suche<br />
◮ Risiko: Degenaration<br />
◮ Abhilfe: Balancierte Bäume (Red-Black-Trees, AVL-Trees)<br />
◮ Löschen: schwierig – Alternative:<br />
◮<br />
◮<br />
Löschung markieren,<br />
Baum gelegentlich neu aufbauen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 56 / 235
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Einfache Rekursion – Fakultät<br />
Einfache Rekursion – Fibonacci-Folge<br />
Iteration:<br />
Rekursion:<br />
n! = n · (n − 1) · . . . · 1<br />
int fact(int n) {<br />
int f = n -- ;<br />
while (n) f *= n --;<br />
return f;<br />
}<br />
1. Abbruchbedingung für das triviale Problem;<br />
2. rekursive Verkleinerung des Problems<br />
n! = n · (n − 1)!<br />
int fact(int n) {<br />
if (n < 2) return 1;<br />
return n * fact(n-1);<br />
}<br />
◮<br />
f n = f n−2 + f n−1<br />
f 0 = f 1 = 1<br />
Übung: Implementation eines Programms zur Berechnung der<br />
Fibonacci-Folge;<br />
◮ Problem der Rekursion: überflüssige Berechnungen – schlechte<br />
Performanz<br />
◮ Verstecktes Problem: Speicherbedarf<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 57 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 58 / 235<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Rekursion – Teile und Herrsche<br />
Rekursion – Türme von Hanoi<br />
◮ Beispiel: Türme von Hanoi;<br />
◮ Aufgaben delegieren<br />
◮ mehrfache Anwendung der rekursiven Funktion<br />
◮ Bewege Turm von Säule A nach Säule B<br />
◮ Ziehe jeweils nur eine Scheibe<br />
◮ Immer muss die kleinere Scheibe über der größeren liegen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 59 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 60 / 235
Algorithmen – Konzepte und Analyse<br />
Rekursion – Türme von Hanoi<br />
1: procedure Hanoi(n, a, b, c)<br />
2: if n = 1 then<br />
3: Write a → b<br />
4: else<br />
5: Hanoi(n − 1, a, c, b)<br />
6: Hanoi(1, a, b, c)<br />
7: Hanoi(n − 1, c, b, a)<br />
8: end if<br />
9: end procedure<br />
Rekursion<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Türme von Hanoi – Auflösung der Rekursion<br />
shiftn(int n, int a, int b, int c) {<br />
push(a); push(b); push(c); push(n);<br />
while ( 1 ) {<br />
while ( n > 1 ) { /* nested while instead of goto */<br />
push(a); push(b); push(c); push(n);<br />
n --; swap(c, b); /* shift(n-1, a, c, b) */<br />
}<br />
show(a, b);<br />
n = pop; c = pop; b = pop; a = pop;<br />
if ( stackempty ) break;<br />
show(a, b);<br />
n --; swap(a, c); /* shift(n-1, c, b, a) */<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 61 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 62 / 235<br />
Algorithmen – Konzepte und Analyse<br />
Iteration statt Rekursion<br />
Rekursion<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Rekursion – Ackermann 1 -Funktion<br />
◮ Rekursion kann immer durch Iteration ersetzt werden;<br />
◮ durch formale Auflösung der Rekursion<br />
◮ durch Algorithmenanalyse<br />
◮ Iteration:<br />
◮ in der Regel performanter;<br />
◮ erfordert oft explizite Speicherverwaltung (meist per Stack)<br />
◮ Implementation meist komplizierter;<br />
◮ Rekursive Algorithmen rekursiv implementieren<br />
◮ meist leichter zu verstehen und zu warten,<br />
◮ iterative Realisierung durch optimierende Compiler.<br />
a(0, n) = n + 1<br />
a(m, 0) = a(m − 1, 1)<br />
a(m, n) = a(m − 1, a(m, n − 1))<br />
m/n 0 1 2 3 4 5 6<br />
0 1 2 3 4 5 6 7<br />
1 2 3 4 5 6 7 8<br />
2 3 5 7 9 11 13 15<br />
3 5 13 29 61 125 253 509<br />
4 13 65533<br />
5 65533<br />
1 Variante von Rózsa Péter<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 63 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 64 / 235
Algorithmen – Konzepte und Analyse<br />
Rekursion<br />
Ackermann-Funktion – Eigenschaften<br />
Algorithmen – Konzepte und Analyse<br />
Rekursion – Übungen<br />
Rekursion<br />
◮ theoretische Informatik<br />
◮ stark anwachsend – Aufwand?<br />
◮ wiederholte Berechnung – Memoization<br />
◮ Benchmarks<br />
◮ Iterative Programme für Fakultät und Fibonacci-Folge<br />
◮ Iteratives Programm für Türme von Hanoi – schwieriger<br />
◮ Iteratives Programm für die Ackermann-Funktion (mit/ohne<br />
Memoization)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 65 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 66 / 235<br />
Algorithmen – Konzepte und Analyse<br />
Aufwandskalkulation<br />
Aufwandskalkulation<br />
Algorithmen – Konzepte und Analyse<br />
Aufwandskalkulation<br />
Aufwandskalkulation rekursiver Algorithmen<br />
◮ Aufwand A;<br />
◮ Problemgröße n;<br />
◮ Komplexität: A = A(n)<br />
◮ Ordnungsfunktion A = O(f (n)) (asymptotisch für große n)<br />
◮ Typische Ordungsfunktionen:<br />
◮ A = O(1)<br />
◮ A = O(log n)<br />
◮ A = O(n)<br />
◮ A = O(n log n)<br />
◮ A = O(n 2 )<br />
◮ A = O(2 n ) (schwierig)<br />
Pro Rekursionsschritt wird vom Eingabefeld:<br />
◮ jedes Element bearbeitet,<br />
◮ ein Element entfernt und der Rest verarbeitet<br />
A n = A n−1 + n<br />
= A n−2 + (n − 1) + n<br />
.<br />
= 1 + 2 + . . . + (n − 1) + n<br />
= n n + 1<br />
2<br />
= O(n 2 )<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 67 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 68 / 235
Algorithmen – Konzepte und Analyse<br />
Aufwandskalkulation<br />
Aufwandskalkulation rekursiver Algorithmen<br />
Pro Rekursionsschritt wird vom Eingabefeld:<br />
◮ jedes Element behandelt,<br />
◮ das Feld in Hälften zerlegt,<br />
◮ beide Hälften verarbeitet.<br />
Algorithmen – Konzepte und Analyse<br />
Aufwandskalkulation – Übung<br />
Aufwandskalkulation<br />
A n = 2 A n/2 + n, n = 2 k<br />
A 2 k = 2 A 2 k−1 + 2 k<br />
A 2 k<br />
2 k = A 2 k−1<br />
2 k−1 + 1<br />
= A 2 k−2<br />
2 k−2 + 1 + 1<br />
.<br />
= k<br />
A 2 k = k 2 k<br />
A n = O(n log n)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 69 / 235<br />
◮ Bestimmen Sie die Ordnungen der Aufwandsfunktionen der bislang<br />
behandelten Algorithmen!<br />
◮ Stellen Sie die in Aufwandskalkulation<br />
grafisch dar!<br />
genannten Ordnungsfunktionen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 70 / 235<br />
Sortieren<br />
Elementares Sortieren<br />
Sortieren<br />
Elementares Sortieren<br />
Sortieren – Grundkonzepte<br />
Sortieren – Vertauschen<br />
◮ vergleichen/vertauschen<br />
◮ intern/extern<br />
◮ Aufwand: N log N ... N 2<br />
◮ Speicherplatz<br />
◮ am Ort<br />
◮ Zusatzspeicher<br />
◮ stabil<br />
◮ Index<br />
◮ Einfluss Vorsortierung<br />
void swap (int a[], int i, int j)<br />
{<br />
int t;<br />
t = a[i];<br />
a[i] = a[j];<br />
a[j] = t;<br />
}<br />
/* exchange without buffer variable */<br />
#define swap(p, q) do { p ^= q; q ^= p; p ^= q; } while (0)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 71 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 72 / 235
Sortieren<br />
Selection Sort<br />
Sortieren<br />
Selection Sort<br />
Selection Sort<br />
1: procedure SelectionSort(Feld)<br />
2: suche das kleinste Element im Feld<br />
3: vertausche es mit dem ersten Element des Feldes<br />
4: sortiere den Rest des Feldes<br />
5: end procedure<br />
◮ A excg (n) = O(n) =⇒ linear; vorteilhaft, wenn Vertauschen aufwendig<br />
◮ A comp (n) = O(n 2 /2)<br />
◮ relativ unempfindlich gegenüber Anordnung der Eingabedaten<br />
Selection Sort – Implementation<br />
selection(int a[], int n)<br />
{<br />
int i, j, imin;<br />
for (i = 1; i < n; i++) {<br />
imin = i;<br />
for (j = i + 1; j
Sortieren<br />
Insertion Sort<br />
Sortieren<br />
Insertion Sort<br />
Insertion Sort – Implementation<br />
insertion(int a[], int n)<br />
{<br />
int i, j, v;<br />
for (i = 2; i v) {<br />
a[j] = a[j - 1];<br />
j--;<br />
}<br />
a[j] = v;<br />
}<br />
}<br />
Insertion Sort – Verlauf<br />
500<br />
450<br />
400<br />
350<br />
300<br />
250<br />
200<br />
150<br />
100<br />
50<br />
’-’<br />
0<br />
0 50 100 150 200 250 300 350 400 450 500<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 77 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 78 / 235<br />
Sortieren<br />
Bubble Sort<br />
Sortieren<br />
Bubble Sort<br />
Bubble Sort<br />
Bubble Sort – Implementation<br />
1: procedure BubbleSort(Feld)<br />
2: vergleiche aufsteigend je zwei folgende Elemente des Feldes<br />
3: vertauschen wenn unsortiert ⊲ extremes Element nun auf Pos. N<br />
4: wiederhole die obigen Schritte für die Elemente bis N − 1<br />
5: end procedure<br />
◮ A excg (n) = O(n 2 /2)<br />
◮ A comp (n) = O(n 2 /2)<br />
◮ ineffizient<br />
◮ leicht zu verstehen<br />
◮ Optimierung: beenden, wenn Durchlauf ohne Vertauschung<br />
bubble(int a[], int n)<br />
{<br />
int i, j;<br />
for (i = n; i >= 1; i--) {<br />
for (j = 2; j a[j]) {<br />
swap(a, j, j-1);<br />
}<br />
}<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 79 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 80 / 235
Sortieren<br />
Performantes Sortieren<br />
Sortieren<br />
Merge Sort<br />
Performantes Sortieren<br />
Mergesort<br />
◮ Komplexität elementarer Sortierverfahren etwa quadratisch<br />
◮ Existieren effizientere Verfahren mit A < O(n 2 ) ?<br />
◮ Idee: teile und herrsche!<br />
1: procedure MergeSort(Feld)<br />
2: teile Feld in Hälften<br />
3: sortiere Hälften per MergeSort<br />
4: verschmelze sortierte Hälften<br />
5: end procedure<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 81 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 82 / 235<br />
Sortieren<br />
Merge Sort<br />
Sortieren<br />
Merge Sort<br />
Mergesort – Eigenschaften<br />
Mergesort – Implementation<br />
◮ Teile und Herrsche<br />
◮ benötigt zusätzlichen Speicher<br />
◮ A = O(n log n)<br />
◮ stabil<br />
◮ unempfindlich gegenüber Vorsortierung<br />
mergesort(int a[], int b[], int l, int r)<br />
{<br />
int i, j, k, m;<br />
if (r > l) {<br />
m = (r+l)/2;<br />
mergesort(a, b, l, m);<br />
mergesort(a, b, m+1, r);<br />
for (i = m+1; i > l; i--) b[i-1] = a[i-1];<br />
for (j = m; j < r; j++) b[r+m-j] = a[j+1];<br />
for (k = l; k
Sortieren<br />
Merge Sort<br />
Sortieren<br />
Merge Sort<br />
Mergesort – Präparation<br />
Mergesort – Verlauf<br />
500<br />
’−’<br />
450<br />
/* wrapper */<br />
msort(int a[], int n)<br />
{<br />
int i, *b;<br />
/* additional memory */<br />
b = (int *) malloc((n+1) * sizeof(int));<br />
mergesort(a, b, 1, n);<br />
}<br />
400<br />
350<br />
300<br />
250<br />
200<br />
150<br />
100<br />
50<br />
0<br />
0 50 100 150 200 250 300 350 400 450 500<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 85 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 86 / 235<br />
Sortieren<br />
Quicksort<br />
Sortieren<br />
Quicksort<br />
Quicksort (C.A.R. Hoare)<br />
Quick Sort – Eigenschaften<br />
1: procedure QuickSort(Feld)<br />
2: wähle ein Element P des Feldes, das einsortiert werden soll<br />
3: partitioniere das Feld (unten alle kleineren, oben alle größeren)<br />
4: füge das Element zwischen den Partitionen ein<br />
5: sortiere beide Partitionen<br />
6: end procedure<br />
1: procedure Partition(Feld, P)<br />
2: Index i l startet von links<br />
3: i l stoppt, wenn sein Element größer als P<br />
4: Index i r läuft entsprechend von rechts<br />
5: Wenn beide Indizes gestoppt sind, vertausche ihre Werte<br />
6: fahre fort, bis die Indizes sich treffen<br />
7: end procedure<br />
◮ A(n) = O(n log n)<br />
◮ gutes Allzweckverfahren<br />
◮ nicht stabil<br />
◮ empfindlich, wenn Partitionierung dauerhaft asymmetrisch<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 87 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 88 / 235
Sortieren<br />
Quick Sort – Implementation<br />
Quicksort<br />
quicksort(int a[], int l, int r)<br />
{<br />
int i;<br />
if (r > l) {<br />
i = partition(a, l, r); /* lower, upper section */<br />
quicksort(a, l, i - 1); /* divide and conquer */<br />
quicksort(a, i + 1, r);<br />
}<br />
}<br />
/* wrapper -- call this */<br />
qsort(int a[], int n)<br />
{<br />
/* wrapper */<br />
quicksort(a, 1, n);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 89 / 235<br />
Sortieren<br />
Quick Sort – Partitionierung<br />
Quicksort<br />
int partition(int a[], int l, int r)<br />
{<br />
int i, j, v, s;<br />
s = a[l - 1]; /* sentinel */<br />
i = l - 1; j = r; /* indexes */<br />
a[i] = v = a[r]; /* to be put to final position */<br />
while (1) {<br />
while (a[++i] < v);<br />
while (a[--j] > v);<br />
if (i >= j) break; /* pointers have met */<br />
swap(a, i, j); /* exchange among sections */<br />
}<br />
swap(a, i, r); /* final position */<br />
a[l - 1] = s;<br />
return (i);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 90 / 235<br />
Sortieren<br />
Quicksort<br />
Sortieren<br />
Quicksort<br />
Quick Sort – Verlauf<br />
Quick Sort – Optimierung<br />
500<br />
’-’<br />
450<br />
400<br />
350<br />
300<br />
250<br />
200<br />
150<br />
100<br />
◮ Beseitigung der Rekursion<br />
◮ expliziter Stapel<br />
◮ Endrekursion<br />
◮ jeweils das größere Teilfeld auf Stapel<br />
◮ das kleinere Teilfeld direkt bearbeiten<br />
◮ Steigerung der Partitionssymmetrie (Median, Random)<br />
◮ Kombination mit Insertion Sort<br />
◮ kleine Teilfelder (n < 20) per Insertion Sort<br />
◮ kleine Teilfelder ignorieren – anschließend Insertion Sort<br />
50<br />
0<br />
0 50 100 150 200 250 300 350 400 450 500<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 91 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 92 / 235
Sortieren<br />
Heap Sort<br />
Sortieren<br />
Heap Sort<br />
Diskurs – Datenstruktur Heap<br />
Heap – Einfügen<br />
◮ Binärbaum mit n Knoten<br />
◮ Speicherung in Array<br />
◮ Heap-Bedingung: alle Pfade<br />
sortiert<br />
◮ schnelle Operationen –<br />
A = O(log n):<br />
◮ Einfügen eines Knotens<br />
◮ Entfernen der Wurzel<br />
◮ automatisch balanciert<br />
◮ Verwendung in<br />
Prioritätswarteschlangen<br />
A<br />
E<br />
G<br />
I M N O<br />
P R S T X<br />
upheap(int k) /* heap repair */<br />
{<br />
int c; /* assume >= 0 */<br />
c = a[k]; /* to be moved */<br />
a[0] = -1; /* sentinel */<br />
while (a[k/2] > c) {<br />
a[k] = a[k/2]; /* up */<br />
k = k/2; /* next level */<br />
}<br />
a[k] = c; /* insert */<br />
}<br />
insert(int c)<br />
{<br />
a[++N] = c; /* append */<br />
upheap(N);<br />
}<br />
A<br />
E<br />
G<br />
I M N O<br />
P R S T X L<br />
A<br />
E<br />
G<br />
I M L O<br />
P R S T X N<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 93 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 94 / 235<br />
Sortieren<br />
Heap Sort<br />
Heap – Entfernen der Wurzel (Remove)<br />
Sortieren<br />
Heap-Remove Implementation<br />
Heap Sort<br />
X<br />
A E<br />
I<br />
G<br />
P M L O<br />
R S T N<br />
/* entry k lower child */<br />
downheap(int k)<br />
{ /* ascending */<br />
int j, c;<br />
c = a[k];<br />
while (k
Sortieren<br />
Heap Sort<br />
Sortieren<br />
Heap Sort<br />
Heap-Sort<br />
Heap-Sort – Implementation<br />
1: procedure HeapSort(array)<br />
2: for all n in nodes do ⊲ build heap<br />
3: downheap(n)<br />
4: end for<br />
5: while nodes in heap do<br />
6: n ← remove() ⊲ reduce heap<br />
7: sorted ← (n, sorted)<br />
8: end while<br />
9: end procedure<br />
downheap(int a[], int n, int k)<br />
{ /* descending */<br />
int j, v = a[k];<br />
while ( k 1 ) {<br />
/* remove maximum */<br />
swap(a, 1, n);<br />
downheap(a, --n, 1);<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 97 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 98 / 235<br />
Sortieren<br />
Heap Sort<br />
Sortieren<br />
Heap Sort<br />
Heap-Sort – Komplexität<br />
Heap-Sort – Eigenschaften<br />
◮ A build = O(N),<br />
◮ A comp = O(N log N)<br />
◮ nicht stabil<br />
◮ unempfindlich gegen Vorsortierung<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 99 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 100 / 235
Sortieren<br />
Heap Sort<br />
Zeichenketten<br />
Suchen in Zeichenketten<br />
Heap-Sort – Verlauf<br />
Suchen von Wörtern in Texten<br />
500<br />
’-’<br />
450<br />
400<br />
350<br />
300<br />
250<br />
200<br />
150<br />
100<br />
◮ gegeben:<br />
◮ Text gespeichert in Feld, Länge n<br />
◮ Zeichenfolge (Wort/Muster, Länge m), die im Text gesucht werden soll<br />
◮ m ≪ n<br />
◮ systematische Suche ab Textanfang<br />
◮ gesucht: Position der Zeichenfolge im Text<br />
◮ eventuelle Probleme bei externer Text-Speicherung:<br />
◮ langsamer Zugriff<br />
◮ Rücksetzen schwierig/unmöglich<br />
50<br />
0<br />
0 50 100 150 200 250 300 350 400 450 500<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 101 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 102 / 235<br />
Zeichenketten<br />
Wortsuche – Brute Force/Naiv<br />
Suchen in Zeichenketten – Naiv<br />
1: procedure NaiveSearch(Word, Text)<br />
2: Text ← Text + Word ⊲ sentinel<br />
3: i ← start(Text)<br />
4: Pos: for all j in Word do ⊲ compare all characters<br />
5: if Text(i + j) ≠ Word(j) then ⊲ mismatch<br />
6: i ← i + 1 ⊲ next position in Text<br />
7: next Pos<br />
8: end if<br />
9: end for<br />
10: return i − 1 ⊲ match found at position<br />
11: end procedure<br />
A = O(m · n)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 103 / 235<br />
Zeichenketten<br />
Suchen in Zeichenketten – Naiv<br />
Brute Force Wortsuche – Implementation<br />
int brutesearch (char *p, char *a)<br />
/* a: text, p: word*/<br />
{<br />
int i, j, M = strlen (p);<br />
strcat(a, p); /* sentinel */<br />
for (i = 0, j = 0; j < M; i++, j++) {<br />
while ( a[i] != p[j] ) {<br />
i += 1 - j;<br />
j = 0;<br />
}<br />
}<br />
return i - M;<br />
}<br />
◮ Beispiel: suche aaaab in aaaaaaaaaaaaaaaaaaaab<br />
◮ wieviele Vergleiche?<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 104 / 235
Zeichenketten<br />
Knuth Morris Pratt – KMP<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Zeichenketten<br />
Knuth Morris Pratt – Wortanalyse<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
◮ Idee: wiederholte Vergleiche an derselben Textstelle vermeidbar?<br />
◮ Vorteil: Wort ist bekannt<br />
◮ Beispiel: suche abend<br />
◮ Annahme: scheitern am d<br />
◮ Schlussfolgerung:<br />
◮ Wort kann an aktueller Stelle nicht stehen<br />
◮ erneute Wortsuche vor der Position von d sinnlos, da dort kein a<br />
◮ =⇒ nächste Wortsuche ab Textposition von d<br />
◮ Problem: Selbstähnlichkeit im Wort, Beispiel gegen<br />
◮ Beispiel: suche gegen<br />
◮ Annahme: scheitern am n<br />
◮ Schlussfolgerung:<br />
◮ Wort kann an aktueller Stelle nicht stehen;<br />
◮ aber: Wort könnte ab dem zweiten g stehen;<br />
◮ =⇒ nächste Wortsuche ab Textposition vom 2. g<br />
◮ Vorteil:<br />
◮ gegen – rot markierte Zeichen bereits gefunden<br />
◮ Wortvergleich ab Position 3 fortsetzen<br />
◮ kein Rücksetzen im Text<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 105 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 106 / 235<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Wortanalyse Selbstähnlichkeit<br />
◮ Bestimme Position next im Wort, bei der nach Scheitern an Position<br />
j die Suche fortgesetzt wird<br />
◮ Beispiel: gegend<br />
j next[j]<br />
0 -1 sinnvoll zur Implementation<br />
1 gegend<br />
0 gegend<br />
2 gegend<br />
0 gegend<br />
3 gegend<br />
1 gegend<br />
4 gegend<br />
2 gegend<br />
5 gegend<br />
0 gegend<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Implementation Suche<br />
int next[len];<br />
int kmpsearch (char *p, char *a)<br />
{<br />
int i, j, M = strlen (p);<br />
initnext (p);<br />
strcat(a, p); /* sentinel */<br />
for (i = 0, j = 0; j < M; i++, j++) {<br />
while ((j >= 0) && (a[i] != p[j])) {<br />
j = next[j];<br />
}<br />
}<br />
return i - M;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 107 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 108 / 235
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Implementation Voranalyse<br />
int next[len];<br />
initnext (char *p)<br />
{<br />
int i = 0, j = -1, m = strlen (p);<br />
next[0] = -1;<br />
while ( i < m ) {<br />
while ((j >= 0) && (p[i] != p[j])) {<br />
j = next[j];<br />
}<br />
i++; j++;<br />
next[i] = j;<br />
}<br />
}<br />
Zeichenketten<br />
Knuth Morris Pratt – Zustandsautomat<br />
◮ Wortsuche per Automat<br />
◮ Automat spezifisch für das gesuchte Wort<br />
◮ Zustandsübergang aus Selbstähnlichkeitstabelle<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
g(0) e(1) g(2) e(3) n(4) d(5)<br />
j next[j]<br />
0 -1<br />
1 0<br />
2 0<br />
3 1<br />
4 2<br />
5 0<br />
Beachte Ähnlichkeit zur eigentlichen Suche!<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 109 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 110 / 235<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Simulation Automat<br />
◮ aus Selbstähnlichkeitstabelle C-Quellen erzeugen<br />
◮ nahezu identische Statements<br />
int kmpauto(char *a)<br />
{<br />
int i = -1;<br />
sm: i ++;<br />
s0: if(a[i] != ’g’) goto sm; i++;<br />
s1: if(a[i] != ’e’) goto s0; i++;<br />
s2: if(a[i] != ’g’) goto s0; i++;<br />
s3: if(a[i] != ’e’) goto s1; i++;<br />
s4: if(a[i] != ’n’) goto s2; i++;<br />
s5: if(a[i] != ’d’) goto s0; i++;<br />
return i-6;<br />
}<br />
j next[j]<br />
0 -1<br />
1 0<br />
2 0<br />
3 1<br />
4 2<br />
5 0<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Simulation Automat<br />
◮ Beobachtung: Sprünge können zusammengefasst<br />
werden<br />
◮ Beispiel: s3 → s1 → s0<br />
g(0) e(1) g(2) e(3) n(4) d(5)<br />
j next[j]<br />
0 -1<br />
1 0<br />
2 -1<br />
3 0<br />
4 2<br />
5 0<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 111 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 112 / 235
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Laufzeitautomat<br />
◮ Idee: Laufzeit-Maschinencode analog zu C-Programm<br />
◮ Hex-Dump Maschinencode (Beispiel Pentium):<br />
0: 55 push %ebp<br />
1: 89 e5 mov %esp,%ebp<br />
3: 8b 55 08 mov 0x8(%ebp),%edx<br />
6: b8 ff ff ff ff mov $0xffffffff,%eax<br />
...<br />
b: 40 inc %eax<br />
c: 80 3c 10 67 cmpb $0x67,(%eax,%edx,1) # ’g’<br />
10: 75 f9 jne b <br />
12: 40 inc %eax<br />
13: 80 3c 10 65 cmpb $0x65,(%eax,%edx,1) # ’e’<br />
17: 75 f3 jne c <br />
19: 40 inc %eax<br />
...<br />
43: 83 e8 07 sub $0x7,%eax # position found<br />
46: 5d pop %ebp<br />
47: c3 ret<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 113 / 235<br />
Knuth Morris Pratt – Laufzeitimplementation<br />
void *kmpauto(char *p) {<br />
char h[]={0x55,0x89,0xe5,0x8b,0x55,0x08,0xb8,0xff,0xff,0xff,0xff};<br />
char z[]={0x83,0xe8,0x00,0x5d,0xc3};<br />
char n[]={0x40,0x80,0x3c,0x10,0x00,0x75,0x00};<br />
int sh = sizeof(h), sn = sizeof(n), sz = sizeof(z);<br />
int i, j, l;<br />
char *c, *s, *t;<br />
l = initnext(p); /* word length */<br />
s = c = (char *) malloc(sh + sz + l * sn); /* code memory */<br />
memcpy(s, h, sh); s += sh; /* head code */<br />
for( t = p, i = 0; *t != ’\0’; t++, i++ ) {<br />
n[4] = *t; /* character to compare */<br />
n[6] = sn * (next[i] - i) - (sn-1) * (next[i]>=0); /* jump */<br />
memcpy(s, n, sn); s += sn; /* append next state */<br />
}<br />
z[2] = l-1; /* return address found */<br />
memcpy(s, z, sz); /* append rest of code */<br />
return((void *) c); } /* code’s address */<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 114 / 235<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Zeichenketten<br />
Suchen in Zeichenketten – Knuth, Morris, Pratt<br />
Knuth Morris Pratt – Laufzeitaufruf<br />
Knuth Morris Pratt – Zusammenfassung<br />
...<br />
int n;<br />
int (*c)();<br />
strcat(a, p); /* sentinel */<br />
c = kmpauto(p); /* Zeiger auf Automaten */<br />
n = c(a); /* Suche */<br />
...<br />
◮ Voranalyse des Suchwortes<br />
◮ Kein Rücksetzen im Text<br />
◮ Implementation über Automaten<br />
◮ Aufwand A = O(n + m)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 115 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 116 / 235
Zeichenketten<br />
Suchen in Zeichenketten – Boyer, Moore<br />
Zeichenketten<br />
Suchen in Zeichenketten – Boyer, Moore<br />
Boyer Moore – BM<br />
Boyer Moore – Konzept<br />
◮ Idee: Vergleich beim letzten Zeichen beginnen<br />
◮ Vorteil: meist keine Übereinstimmung<br />
◮ Folge: große Sprünge vorwärts<br />
◮ Voraussetzung: Rückwärtspositionierung erlaubt<br />
Prinzipien:<br />
◮ Vergleich am Wortende<br />
◮ bad/missing character<br />
◮ optimal: Textzeichen fehlt in Wort =⇒ Sprung um Wortlänge<br />
◮ sonst Wort verschieben bis Übereinstimmung mit Textzeichen<br />
◮ good suffix<br />
◮ ohne Selbstähnlichkeit große Sprünge<br />
◮ Selbstähnlichkeit am Ende (analog KMP)<br />
Beispiel zu bad character:<br />
◮ Suche gegen in gegeben<br />
◮ b fehlt im Wort<br />
◮ =⇒ Sprung um Wortlänge voraus<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 117 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 118 / 235<br />
Zeichenketten<br />
Boyer Moore – Analyse Bad Character<br />
Suchen in Zeichenketten – Boyer, Moore<br />
#define ASCII_LEN 256<br />
int skip[ASCII_LEN];<br />
void initskip(char *p)<br />
{<br />
int m, j;<br />
char c;<br />
m = strlen(p);<br />
for ( j = 0; j < ASCII_LEN; j++)<br />
skip[j] = m; /* normally skip word length */<br />
for ( j = 0; p[j] != ’\0’; j++ )<br />
skip[(int) p[j]] = m - j - 1;<br />
/* skip to rightmost character */<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 119 / 235<br />
Zeichenketten<br />
Boyer Moore – Implementation<br />
Suchen in Zeichenketten – Boyer, Moore<br />
/* Bad Character */<br />
bmsearch (char *p, char *a)<br />
{<br />
int i, j, t, M = strlen (p);<br />
initskip (p);<br />
strcat(a, p); /* sentinel */<br />
for (i = M - 1, j = M - 1; j >= 0; i--, j--) {<br />
while (a[i] != p[j]) {<br />
t = skip[a[i]];<br />
/* equivalent to naive method for t = 0 */<br />
i += (M - j > t) ? M - j : t;<br />
j = M - 1;<br />
}<br />
}<br />
return i;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 120 / 235
Zeichenketten<br />
Suchen in Zeichenketten – Boyer, Moore<br />
Zeichenketten<br />
Suchen in Zeichenketten – Rabin, Karp<br />
Boyer Moore – Fazit<br />
Rabin Karp – RK<br />
◮ optimal: Kombination aus<br />
◮ good suffix<br />
◮ bad character<br />
◮ erfordert Rücksetzen im Text<br />
◮ Aufwand:<br />
worst case: A = O(n + m)<br />
durchschnittlich: A = O( n m )<br />
◮ extrem performant<br />
◮ Idee: Hashcode-Vergleich<br />
◮ Vorbereitung: Hash für Wort<br />
◮ Suche: Texthash an Wortposition vergleichen<br />
◮ Trick: Hash-Berechnung per Schiebeoperation<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 121 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 122 / 235<br />
Zeichenketten<br />
Rabin Karp – Algorithmus<br />
Suchen in Zeichenketten – Rabin, Karp<br />
Zeichenketten<br />
Rabin Karp – Hashberechnung<br />
Suchen in Zeichenketten – Rabin, Karp<br />
1: procedure RKSearch(Word, Text)<br />
2: h ← hash(Word)<br />
3: w ← length(Word)<br />
4: for i, TextLength do<br />
5: if hash(Text[i . . . i + w]) = h then<br />
6: break ⊲ match<br />
7: end if<br />
8: end for<br />
9: return i ⊲ text position of match<br />
10: end procedure<br />
◮ Nachprüfung<br />
◮ effiziente Hash-Berechnung?<br />
◮ Hashrechnung per Modulorechnung über Polynom (Horner-Schema)<br />
◮ implizite Modulorechnung (Modul q)<br />
◮ Basis b entsprechend Anzahl verschiedener Symbole<br />
◮ Position i in Text a, Hash h i über m Zeichen<br />
h i = a i b m−1 + a i+1 b m−2 + a i+2 b m−3 + . . . + a i+m−1<br />
h i+1 = a i+1 b m−1 + a i+2 b m−2 + . . . + a i+m−1 b + a i+m<br />
=⇒ h i+1 = (h i − a i b m−1 )b + a i+m<br />
h i+1 = h i b − a i B + a i+m<br />
B = b m<br />
◮ Prinzip der Teleskopsumme<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 123 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 124 / 235
Zeichenketten<br />
Rabin Karp – Implementation<br />
Suchen in Zeichenketten – Rabin, Karp<br />
#define b 256 /* Base, Alphabet’s size */<br />
#define q 8388593 /* Modulus, b q without overrun */<br />
int rksearch (char *p, char *a) /* assume strcat(a, p) */<br />
{<br />
unsigned int i, B = 1, hp = 0, ha = 0, M = strlen (p);<br />
for (i = 1; i < M; i++) B = (b * B) % q;<br />
for (i = 0; i < M; i++) {<br />
hp = (hp * b + p[i]) % q; /* prepare word hash */<br />
ha = (ha * b + a[i]) % q; /* prepare text hash */<br />
}<br />
for (i = 0; hp != ha; i++) { /* run through all text */<br />
ha = (ha + b * q - a[i] * B) % q; /* b q - ai B > 0 */<br />
ha = (ha * b + a[i + M]) % q;<br />
}<br />
return i;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 125 / 235<br />
Rabin Karp – Fazit<br />
Zeichenketten Suchen in Zeichenketten – Rabin, Karp<br />
◮ keine komplizierte Voranalyse<br />
◮ Hash-Berechnung erfordert Nachvergleich<br />
◮ Aufwand: A = O(n + m) (ähnlich KMP)<br />
◮ kein Rücksetzen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 126 / 235<br />
Zeichenketten Zeichenkettenklassifikation<br />
Phonetische Klassifikation – Soundex-Algorithmus<br />
Idee: Wörter von ähnlichem Klang klassifizieren<br />
◮ Phonetik – Code → Phonem<br />
◮ Vokale<br />
◮ Konsonanten – Anatomie/Lautbildungshorizonte:<br />
◮ Kehlkopf<br />
◮ Rachen<br />
◮ Gaumen (weich/hart)<br />
◮ Zähne/Zahndamm<br />
◮ Lippen<br />
◮ Nase<br />
◮ Artikulation:<br />
◮ Verschlusslaute, Dauerlaute<br />
◮ stimmhaft, stimmlos, behaucht<br />
Knuth: The Art of Computer Programming<br />
Soundex-Algorithmus<br />
Zeichenketten<br />
1: procedure Soundex(word)<br />
2: notiere Anlaut (Anfangsbuchstabe)<br />
3: ignoriere Vokale (und H, W)<br />
4: vereinzele Zeichen<br />
5: klassifiziere bis zu drei Zeichen<br />
6: fülle ggf. mit Nullen auf<br />
7: end procedure<br />
Zeichenkettenklassifikation<br />
Soundex-Klassifikation<br />
Code Phoneme Zeichen<br />
1 Labiale B, F, P, V<br />
2 Gutturale, Frikative C, G, J, K, Q, S, X, Z<br />
3 Dentale D, T<br />
4 laterale Approximanten L<br />
5 Nasale M, N<br />
6 Vibranten R<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 127 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 128 / 235
Zeichenketten<br />
Zeichenkettenklassifikation<br />
Soundex-Algorithmus – Implementierung<br />
#include /* isalpha() */<br />
char *soundex(char *str)<br />
{ /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */<br />
char *tbl = "01230120022455012623010202";<br />
static char sndx[] = "A000";<br />
int cnt = 0;<br />
sndx[cnt++] = (char)toupper(*str++); /* first character */<br />
while(*str != ’\0’ && cnt < sizeof(sndx)-1) {<br />
if(isalpha(*str) && *str != *(str-1)) {<br />
sndx[cnt] = tbl[toupper(*str) - ’A’];<br />
if(sndx[cnt] != ’0’) ++cnt;<br />
}<br />
++str;<br />
}<br />
return(sndx);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 129 / 235<br />
Soundex – Anwendung<br />
Zeichenketten Zeichenkettenklassifikation<br />
◮ Soundex-Werte:<br />
◮ Soundex(’Heidelberg’) = H341<br />
◮ Soundex(’Hotel’) = H340<br />
◮ Soundex(’Meier’) = M600<br />
◮ Soundex(’Mayr’) = M600<br />
◮ orientiert am Englischen<br />
◮ extrem einfach<br />
◮ A = O(1)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 130 / 235<br />
Zeichenketten<br />
Zeichenkettenklassifikation<br />
Kompression<br />
Verlustlose Kompression<br />
Markov-Ketten<br />
Lauflängenkompression – Run Length Encoding (RLE)<br />
◮ Häufigkeit von Zeichen in Texten sprachabhängig<br />
◮ Häufigkeit von Digrammen, Trigrammen, N-Grammen<br />
◮ Beispiel – im Deutschen:<br />
◮ -s-c-h-, sehr wahrscheinlich<br />
◮ -s-c-e-, eher unwahrscheinlich<br />
◮ Wahrscheinlichkeit abhängig von vorangehenden Zeichen<br />
◮ Anwendung:<br />
◮ Spracherkennung<br />
◮ OCR (Optical Character Recognition)<br />
◮ Passwortgenerierung<br />
◮ Idee: manchmal tritt ein Zeichen mehrfach in Folge auf<br />
◮ Verdichten: Angabe von Zeichen und Anzahl<br />
◮ Anwendung:<br />
◮ kontraststarke Raster-Grafiken<br />
◮ Fax<br />
◮ Text mit Wiederholungszeichen (Leerzeichen)<br />
Jon Bentley: Programming Pearls, 2nd Ed., section 15.3<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 131 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 132 / 235
Kompression<br />
Lauflängenkompression – Varianten<br />
Verlustlose Kompression<br />
Kompression<br />
Lauflängenkompression – Bitmuster<br />
Verlustlose Kompression<br />
Text: AAAABBBAABBBBBCCCCCCCCABCQAAA<br />
◮ einfach: Paare (Anzahl/Zeichen)<br />
◮ 4A3B2A5B8C1A1B1C1Q3A<br />
◮ Aufblähen durch einfache Zeichen<br />
◮ Einzelzeichen ohne Zählung:<br />
◮ 4A3B2A5B8CABCQ3A<br />
◮ Ziffern können nicht kodiert werden<br />
◮ Abhilfe: Escape-Zeichen (Q – selten!)<br />
◮ QDABBBAAQEBQHCABCQ@AAA<br />
◮ Codes repräsentieren Zeichen oder Anzahlen<br />
◮ Kodierung Escape-Zeichen<br />
................<br />
.....XXXXXXX....<br />
....X.....XX....<br />
...XX......X....<br />
...X.......X....<br />
..XX............<br />
..XX............<br />
..XX............<br />
...X............<br />
...XX...........<br />
....XX.....X....<br />
.....XXXXX......<br />
................<br />
................<br />
◮ nur Anzahlen speichern<br />
◮ Zeile beginnt mit 0-Bit<br />
◮ 16<br />
5 7 4<br />
4 1 5 2 4<br />
3 2 6 1 4<br />
3 1 7 1 4<br />
2 2 12<br />
...<br />
◮ alternativ: Zeilenlänge angeben<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 133 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 134 / 235<br />
Kompression<br />
Verlustlose Kompression<br />
Lauflängenkompression – Implementierung<br />
#define out(z, k) do { fputc(k, ENC); fputc(z, ENC); \<br />
i = 1; n += 2; } while(0)<br />
int rlenc(FILE *F, FILE *ENC)<br />
{<br />
int i = 1, n = 0;<br />
char c0, c;<br />
if ( ( c0 = fgetc(F) ) == EOF ) return 0;<br />
while ( ( c = fgetc(F) ) != EOF ) {<br />
if ( c == c0 )<br />
if ( ++i > 255 ) out(c, 255);<br />
else out(c0, i);<br />
c0 = c;<br />
}<br />
out(c0, i);<br />
return n;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 135 / 235<br />
Kompression Verlustlose Kompression<br />
Lauflängenkompression – Übung<br />
◮ Programme mit:<br />
◮ Bitmusterkompression<br />
◮ Escape-Zeichen<br />
◮ Zeichenfolgenwiederholungen<br />
◮ Programme zur Lauflängendekodierung<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 136 / 235
Kompression<br />
Verlustlose Kompression<br />
Kompression<br />
Entropiekodierung<br />
Huffman-Kompression – Entropiekodierung<br />
◮ Idee: häufige Zeichen durch kurze Codes speichern<br />
◮ Voraussetzung: Häufigkeitsauswertung<br />
◮ Günstig bei unterschiedlichen Zeichenhäufigkeiten<br />
◮ Informationsgehalt<br />
◮ Entropie<br />
Entropie (Shannon)<br />
Zeichen z<br />
Alphabet mit n Zeichen z i , i = 1 . . . n<br />
Häufigkeit/Wahrscheinlichkeit p:<br />
p = p(z)<br />
Informationsgehalt I eines Zeichens z (Anzahl erforderlicher Bits):<br />
I (z) = log 2<br />
1<br />
p(z) = − log 2 p(z)<br />
Entropie H für einen Datensatz mit m verschiedenen Zeichen:<br />
m∑<br />
H = − p i log 2 p i<br />
i=1<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 137 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 138 / 235<br />
Kompression<br />
Entropiekodierung<br />
Kompression<br />
Entropiekodierung<br />
Entropie – Information<br />
◮ Beispiel: Text mit drei verschiedenen Zeichen<br />
◮ Häufigkeiten:<br />
n 1 n 2 n 3 H<br />
1 4 100 0,31<br />
5 10 90 0,72<br />
10 30 65 1,27<br />
35 35 35 1,59<br />
◮ Entropie H steigt mit Gleichmäßigkeit der Verteilung<br />
◮ Thermodynamik: Entropie als Maß für Unordnung<br />
◮ Information vs. Chaos<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 139 / 235<br />
Entropie-Bestimmung – Implementation<br />
#include <br />
#include <br />
#define ALEN 256<br />
int main() {<br />
int k[ALEN] = {};<br />
int c, i, n = 0, z = 0;<br />
double h = 0.0, p, f;<br />
while ( ( c = getchar() ) != EOF ) {<br />
k[c] ++; n ++; /* count characters frequency and total */<br />
}<br />
f = 1.0 / n; /* use double precision arithmetic */<br />
for ( i = 0; i < ALEN; i ++ ) {<br />
if ( k[i] ) {<br />
p = f * k[i]; h -= p * log2(p);<br />
}<br />
}<br />
printf("%lg\n", h);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 140 / 235
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Huffman-Kompression<br />
Huffman-Kompression – Baumkodierung<br />
Huffman-Kodierung<br />
Text: ABRACADABRA (11 Zeichen × 8 bit = 88 bit)<br />
(11)<br />
Beispiel-Code:<br />
A<br />
( 6)<br />
5 A: 0<br />
0<br />
1<br />
2 B: 10<br />
1 C: 1110<br />
1 D: 1111<br />
B<br />
( 4)<br />
0<br />
1<br />
2 R: 110 R<br />
( 2)<br />
0<br />
1<br />
1. zähle Häufigkeit aller Zeichen<br />
2. sortiere Zeichen nach Häufigkeit (Binärbaum – Heap)<br />
3. bilde Huffman-Codes durch Traversierung<br />
4. Speichere Coding<br />
5. Speichere Codes aller Zeichen<br />
0<br />
1<br />
Code: 0 10 110 0 1110 0 1111 0 10 110 0 (23 Bit)<br />
C<br />
D<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 141 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 142 / 235<br />
Huffman-Baum – Beispiel<br />
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Aufbau Huffman-Baum – Beispiel<br />
Huffman-Kompression<br />
Zeichenhäufigkeit (Beispiel)<br />
Zeichen Anzahl<br />
a 94<br />
b 51<br />
c 155<br />
d 100<br />
e 257<br />
f 124<br />
g 25<br />
h 78<br />
i 212<br />
j 14<br />
Frequency Heap<br />
(1110)<br />
Huffman Code Tree<br />
(1110)<br />
1 0<br />
(641) (469)<br />
1 0 1 0<br />
(362) (279) e(257) i(212)<br />
1 0 1 0<br />
(194) (168) c(155) f(124)<br />
0 1 0 1<br />
a(94) d(100) h(78) (90)<br />
1 0<br />
b(51) (39)<br />
1 0<br />
g(25) j(14)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 143 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 144 / 235
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Huffman-Kompression<br />
Aufbau Huffman-Baum – Beispiel<br />
Coding-Tabelle des Beispiels<br />
Zeichen Anzahl Code<br />
a 94 1110<br />
b 51 11011<br />
c 155 101<br />
d 100 1111<br />
e 257 01<br />
f 124 100<br />
g 25 110101<br />
h 78 1100<br />
i 212 00<br />
j 14 110100<br />
11111110 11011010 01101010 11111000 11100010 00100111 10101 ?<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 145 / 235<br />
Huffman-Codierung – Implementation<br />
#define ALEN 256 /* symbols in alphabet */<br />
#define BLKSIZE 0x10000<br />
compress(FILE *F, FILE *C)<br />
{<br />
int M, N;<br />
char a[BLKSIZE]; /* buffer */<br />
int sym[2*ALEN], cnt[2*ALEN], pnt[2*ALEN];<br />
int code[ALEN], len[ALEN];<br />
M = input(F, a, BLKSIZE); /* read block */<br />
N = frequency(a, cnt); /* N different symbols */<br />
initheap(sym, cnt, ALEN); /* construct heap */<br />
hufftree(N, sym, cnt, pnt); /* coding tree */<br />
huffcode(pnt, code, len); /* codes and lengths */<br />
output(C, code, len, a, M);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 146 / 235<br />
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Huffman-Kompression<br />
Huffman-Codierung – indirektes Einfügen Heap<br />
/* move symbol k in heap (size N) down to */<br />
/* appropriate position - given by it’s count */<br />
void idownheap(int sym[], int cnt[], int N, int k)<br />
{<br />
int j, c;<br />
c = sym[k];<br />
while (k
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Huffman-Kompression<br />
Huffman-Codierung – Baum<br />
void hufftree(int N, int sym[], int cnt[], int pnt[])<br />
{<br />
int t;<br />
while (N > 1) {<br />
t = sym[1]; sym[1] = sym[N--]; /* remove heap root */<br />
idownheap(sym, cnt, N, 1); /* and reorder heap */<br />
cnt[ALEN+N] = cnt[sym[1]] + cnt[t]; /* join lowest */<br />
pnt[t] = ALEN + N; /* old root: parents lower child */<br />
pnt[sym[1]] = -ALEN - N; /* new root: upper child */<br />
sym[1] = ALEN + N; /* replace root by lowest pair */<br />
idownheap(sym, cnt, N, 1); /* reorder heap */<br />
}<br />
pnt[ALEN + N] = 0; /* tree’s root */<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 149 / 235<br />
Huffman-Codierung – Code-Bestimmung<br />
void huffcode(int pnt[], int code[], int len[])<br />
{<br />
int i, j, k, t, x;<br />
for (k = 0; k set bit */<br />
x += j; t = -t;<br />
}<br />
t = pnt[t]; /* move up tree */<br />
j += j; i++; /* next bit, increase code length*/<br />
}<br />
code[k] = x; len[k] = i;<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 150 / 235<br />
Kompression<br />
Huffman-Kompression<br />
Kompression<br />
Huffman-Kompression<br />
Kompletter Huffman-Baum (für Programm-Quelltext)<br />
Huffman-Codierung – Fazit<br />
N(45)<br />
(7846)<br />
1<br />
0<br />
(4477)<br />
(3369)<br />
0 1<br />
1<br />
0<br />
0x20(1934) (2543)<br />
(1852)<br />
(1517)<br />
1<br />
0<br />
1 0<br />
1 0<br />
(1360)<br />
(1183)<br />
(998)<br />
(854)<br />
(785)<br />
(732)<br />
1<br />
0<br />
1 0<br />
1<br />
0<br />
1<br />
0<br />
1 0 0 1<br />
(702)<br />
(658)<br />
(605) (578)<br />
(527)<br />
(471)<br />
(431)<br />
(423)<br />
(406) (379) 0xA(365) (367)<br />
1<br />
0 0 1<br />
1 0 1 0<br />
1 0<br />
1 0 0 1 1 0 0 1 0 1 0 1<br />
(361)<br />
(341) e(317) n(341)<br />
(315) (290) i(289) t(289) (272)<br />
(255)<br />
(240) (231) ((212) r(219) )(212) (211) ,(198) ;(208) c(189) (190) o(183) (184)<br />
1 0<br />
1 0<br />
1 0 1 0 0 1 0 1 0 1 1 0<br />
1 0 0 1 1 0<br />
f(183) (178)<br />
(173) (168)<br />
(162) (153) =(147) (143) d(135) s(137) a(123) (132) *(119) (121) l(117) (114)<br />
(108) (103)<br />
0x9(94) (96) p(93) (91)<br />
1 0 1 0 0 1 0 1<br />
1 0<br />
1<br />
0 1 0 0 1 1 0 0 1 0 1 0 1 1 0<br />
(90) (88) h(87) u(86) [(84) (84) E(78) ](84) (78) (75)<br />
(73)<br />
(70) 0x22(66) (66)<br />
b(60) (61) m(57) (57) {(54) }(54) +(50) (53)<br />
0(47) (49) L(46) (45)<br />
1 0<br />
0 1 0 1 1 0 0 1 1 0 0 1 1 0 0 1<br />
1 0 1 0 0 1 1 0<br />
T(45) (44) (44)<br />
1(42) (42)<br />
k(39) (39) /(37) x(38) z(37) (36) >(34) A(36) -(34)
Kompression<br />
Verlustbehaftete Kompression – DCT<br />
Diskrete Kosinus-Transformation – DCT (JPEG)<br />
Kompression<br />
Verlustbehaftete Kompression – DCT<br />
Diskrete Kosinus-Transformation – DCT<br />
Abbildung:<br />
◮ Idee: Signal-Approximation durch Überlagerung von Schwingungen<br />
◮ äquidistantes Signal x i über n Samples (z.B. Farbwerte in Pixelfolge)<br />
◮ Mittelwert + Oberschwingungen<br />
◮ Frequenz Grundschwingung: halbe Periode<br />
◮ Amplituden A k = ?<br />
X 0 =<br />
√<br />
1<br />
n<br />
i=0<br />
X = dct(x), R → R<br />
∑n−1<br />
√<br />
2 ∑n−1<br />
x i , X k = x i cos<br />
n<br />
i=0<br />
π(2i + 1)k<br />
, k = 1 . . . n − 1<br />
2n<br />
A 0 =<br />
√<br />
1<br />
n X 0, A k =<br />
√<br />
2<br />
n X k, k = 1 . . . n − 1<br />
http://www.faqs.org/faqs/compression-faq<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 153 / 235<br />
Vorteil:<br />
◮ rein reelle Rechnung<br />
◮ sehr performant berechenbar (ähnlich Fast Fourier Transformation,<br />
A = O(n log n))<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 154 / 235<br />
Kompression<br />
Verlustbehaftete Kompression – DCT<br />
Kompression<br />
Verlustbehaftete Kompression – DCT<br />
DCT – Signalapproximation<br />
DCT – Approximation<br />
DCT - Signalapproximation<br />
140<br />
120<br />
Signal<br />
11. Oberschwingung<br />
Approximation<br />
◮ Inverse DCT approximiert Ursprungssignal x<br />
◮ Amplituden fallen oft mit steigender Frequenz<br />
Grauwert 0-255<br />
100<br />
80<br />
60<br />
√ √<br />
1 2<br />
x i =<br />
n X 0 +<br />
n<br />
x = idct(X)<br />
∑n−1<br />
X k cos<br />
k=1<br />
π(2i + 1)k<br />
, i = 0 . . . n − 1<br />
2n<br />
0 2 4 6 8 10 12 14<br />
Pixel xi<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 155 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 156 / 235
DCT – Kompression<br />
Kompression Verlustbehaftete Kompression – DCT<br />
◮ Idee: Quantisierung<br />
◮ untere Bits der Amplituden ausblenden<br />
◮ z.B. 0xb9 & ~7 = 0xb8<br />
◮ Anzahl Ausblendungs-Bits variabel<br />
◮ Ausblendung ↑ Qualität ↓ Kompression ↑<br />
◮ Amplituden entropie-kodieren<br />
◮ optional: statt Amplituden ihre Differenzen kodieren<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 157 / 235<br />
Kompression<br />
DCT-Kompression – Beispiel<br />
Folge von 16 Pixeln (Grauwerte 0–255)<br />
x i X k X c x a<br />
101 380 380 102<br />
69 7 0 62<br />
64 -66 -64 69<br />
140<br />
82 -19 -16 81<br />
120<br />
89 46 48 80<br />
114 20 16 114<br />
140 11 16 140<br />
100<br />
130 6 0 129<br />
126 6 0 121<br />
80<br />
111 9 16 114<br />
90 12 16 97 60<br />
81 10 16 85<br />
76 -5 0 72<br />
75 -3 0 74<br />
86 -1 0 90<br />
86 2 0 91<br />
Grauwert 0-255<br />
Verlustbehaftete Kompression – DCT<br />
DVT - Quantisierung 4/8 bit<br />
Signal<br />
Approximation<br />
0 2 4 6 8 10 12 14<br />
Pixel xi<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 158 / 235<br />
Kompression<br />
Verlustbehaftete Kompression – DCT<br />
Kryptologie<br />
Kryptologie – Prinzipien<br />
DCT – Anwendung JPEG<br />
Kryptologie – Prinzip<br />
1. Farbraumkonvertierung RGB → YCbCr<br />
2. Blockbildung 8 × 8 Pixel<br />
3. zweidimensionale DCT über Block<br />
4. Quantisierung (skalierbar)<br />
5. Entropiekodierung<br />
6. Artefakte<br />
◮ Nachricht M<br />
◮ Schlüssel K<br />
◮ Verschlüsselungsverfahren E<br />
◮ Chiffre C = E(M, K)<br />
◮ Entschlüsselungsverfahren D (oft ähnlich E)<br />
◮ Entschlüssel K ′ (oft leicht aus K zu ermitteln)<br />
◮ M = D(C, K ′ )<br />
◮ Kerckhoff-Prinzip<br />
◮ Problem: Sicherheit der Schlüssel<br />
JPEG<br />
PNG<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 159 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 160 / 235
Kryptologie<br />
Kryptologie – Elementarverfahren<br />
Kryptologie<br />
Kryptologie – Elementarverfahren<br />
Kryptologie – Typen<br />
Caesar-Chiffre<br />
◮ Klassische Verfahren<br />
◮ Caesar-Chiffre (Verschiebung)<br />
◮ Substitutionschiffre (A, B, C, . . . → P, D, G, . . . )<br />
◮ Vigenere-Chiffre (unterschiedliche Verschiebung)<br />
◮ Vernam-Chiffre<br />
◮ Schlüssellänge = Nachrichtenlänge<br />
◮ One-Time-Pad (Zufall)<br />
◮ XOR<br />
◮ Symmetrische Verfahren<br />
◮ DES (Data Encryption Standard), 3DES (Blockchiffre)<br />
◮ AES (Advanced Encryption Standard), Serpent, Twofish<br />
◮ Asymmetrische Verfahren<br />
◮ RSA (Rivest, Shamir, Adleman)<br />
◮ Elgamal<br />
◮ Alphabet A, n = |A|<br />
◮ Verschiebung k<br />
◮ Zeichen z ′ ← (z + k) mod n<br />
◮ k leicht zu erraten<br />
Beispiel: Rot13 (in Perl):<br />
#!/usr/bin/perl -p<br />
y/a-zA-Z/n-za-mN-ZA-M/;<br />
Übung: Rot13 in beliebiger Programmiersprache<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 161 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 162 / 235<br />
Kryptologie<br />
Symmetrische Kryptologie – DES<br />
Symmetrische Verschlüsselung – DES (IBM)<br />
Kryptologie<br />
Public Key – Diffie Hellman<br />
Asymmetrische Kryptologie<br />
◮ blockweise (64 bit) Verschlüsselung (56 Bit)<br />
◮ iteratives Vertauschen in 19 Schritten<br />
C = E(M, K)<br />
M = D(C, K)<br />
◮ verbessert als Triple-DES (3DES mit 112 Bit Key K)<br />
K = (K 1 , K 2 )<br />
C = E(D(E(M, K 1 ), K 2 ), K 1 )<br />
M = D(E(D(C, K 1 ), K 2 ), K 1 )<br />
Idee:<br />
◮ jeder Teilnehmer verwendet ein Schlüsselpaar (G, P)<br />
◮ G geheim, P öffentlich<br />
◮ G und P einfach gemeinsam berechenbar<br />
◮ M = G(P(M))<br />
◮ Ableiten von G aus P schwierig (Primzahlrechnung)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 163 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 164 / 235
Kryptologie<br />
Verschlüsselung und Primzahlen<br />
Asymmetrische Kryptologie<br />
Kryptologie<br />
Asymmetrische Kryptologie<br />
Public Key – RSA – Schlüssel-Konstruktion<br />
Berechne:<br />
Teiler von:<br />
1983731287 × 943765649<br />
1781137561759059887<br />
1. wähle Primzahlen p, q ≫ 1 (real über 100 Stellen)<br />
2. N = p · q, z.B. p = 47, q = 79 ⇒ N = 3713<br />
3. N öffentlich<br />
4. berechne Z = (p − 1)(q − 1), hier Z = 3588<br />
5. wähle Primzahl d > p, q, z.B. d = 97<br />
6. bestimme e mit (e · d) mod Z = 1 (z.B. e = 37, meist relativ klein)<br />
7. e öffentlich, d geheim<br />
8. p, q, Z verwerfen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 165 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 166 / 235<br />
Kryptologie<br />
Asymmetrische Kryptologie<br />
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Public Key – RSA<br />
Public Key – RSA – Umsetzung<br />
◮ Verschlüsseln<br />
◮ öffentliche Schlüssel N und e des Adressaten beschaffen<br />
◮ C = M e mod N<br />
◮ Beispielnachricht: ATTACK..., M = 01 20 20 01 03 11 . . .<br />
◮ blockweise: 0120 37 mod 3713 = 1404, . . .<br />
◮ Entschlüsseln<br />
◮ M = C d mod N<br />
◮ im Beispiel: 1404 97 mod 3713 = 0120<br />
◮ Schwierigkeiten:<br />
◮ Primzahlen p, q finden<br />
◮ Arithmetik großer Zahlen (Karatsuba, FFT)<br />
◮ öffentlichen Schlüssel e aus Geheimschlüssel d finden (erweiterter<br />
Euklidischer Algorithmus)<br />
◮ deutlich rechenaufwändiger/langsamer als symmetrische Verfahren<br />
◮ Kombination mit symmetrischen Verfahren<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 167 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 168 / 235
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Diskurs: Multiplikation großer Zahlen<br />
Karatsuba: teile und herrsche rekursiv A = O(n log 2 3 ) ≈ O(n 1,585 )<br />
x = x 2n−1 b 2n−1 + . . . + x n b n + x n−1 b n−1 + . . . + x 0<br />
= x h B + x l , B = b n<br />
y = y h B + y l<br />
Beispiel: 4853762169725189<br />
} {{ }<br />
2 n=16<br />
= } 48537621 {{ } ·<br />
x h<br />
x · y = (x h B + x l ) · (y h B + y l )<br />
B=10 n<br />
{}}{<br />
10 8 + 69725189 } {{ }<br />
x l<br />
= x h y<br />
}{{} h B 2 + (x h y l + x l y h ) B + x<br />
} {{ } l y<br />
}{{} l<br />
H<br />
M+H+L<br />
L<br />
M = (x h − x l ) · (y l − y h ) = x h y l + x l y h − x h y h − x l y l<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 169 / 235<br />
Kryptologie<br />
Arithmetik mit großen Zahlen – Typen<br />
◮ Datentyp (Ziffer, Zahl, Vorzeichen)<br />
◮ Deklaration<br />
Kryptologie – Arithmetik großer Zahlen<br />
#define BASE 10 /* minimize conversion effort at I/O */<br />
typedef int digit;<br />
struct bignum {<br />
int n; /* number of digits */<br />
int neg; /* sign: 1 - negative, 0 - otherwise */<br />
digit *d; /* digits stored in big endian */<br />
};<br />
typedef struct bignum bignum;<br />
◮ Konstruktor<br />
bignum *newnum(int n, int neg, digit *d) {<br />
bignum *b = (bignum *) resize(NULL, sizeof(bignum));<br />
b->n = n; b->neg = neg;<br />
b->d = (digit *) resize(b->d, n * sizeof(digit));<br />
return b;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 170 / 235<br />
Kryptologie Kryptologie – Arithmetik großer Zahlen<br />
Arithmetik mit großen Zahlen – Operationen<br />
◮ Beispiel Addition(Annahme: Vorzeichen, Ziffernanzahl gleich)<br />
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Arithmetik mit großen Zahlen – Übungen<br />
◮<br />
bignum *add(bignum *x, bignum *y) {<br />
int i, n = x->n; digit *u = x->d, *v = y->d, *w;<br />
bignum *z = newnum(n+1, x->neg, NULL); w = z->d;<br />
for ( i = 0; i < n; i ++ ) *(w++) = *(u++) + *(v++);<br />
carry(z); return z;<br />
}<br />
Übertrag<br />
void carry(bignum *a) {<br />
digit c = 0, *d = a->d; int n = a->n;<br />
for (d += n; n; n--) {<br />
c += *(--d); *d = c % BASE; c /= BASE;<br />
if ( *d < 0 ) { *d += BASE; c--; }<br />
}<br />
}<br />
◮ Bibliothek implementieren mit<br />
◮ Ein-, Ausgabe,<br />
◮ Addition, Negation, Subtraktion,<br />
◮ Multiplikation (klassisch und Karatsuba),<br />
◮ Hilfsfunktionen (Speicherverwaltung, Normalisierung, Vergleich);<br />
◮ Mit Standardbibliotheken vergleichen.<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 171 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 172 / 235
Diskurs: Modulorechnung<br />
Kryptologie Kryptologie – Arithmetik großer Zahlen<br />
◮ Beispiel: Modul M = 13<br />
◮ implizite Modulorechnung<br />
◮ 7 + 11 =?, 15 + 21 =?<br />
◮ 7 · 5 =?, 8 · 9 =?<br />
◮ 8 − 3 =?, 3 − 7 =?, 7 − 12 = x ⇔ x + 12 = 7<br />
◮ 6 · 11 =?, 6 · 6 −1 = 1 ⇒ 6 −1 = 11 (Inverse)<br />
Kryptologie<br />
Modulorechnung für Potenzen<br />
Kryptologie – Arithmetik großer Zahlen<br />
◮ Beispiel: 87 173 mod 97 =?<br />
◮ implizite Modulorechnung: a ⊙ b ≡ (a · b) mod M<br />
◮ 87 173 mod 97 = 87<br />
}<br />
⊙ 87 ⊙ 87<br />
{{<br />
. . . 87 ⊙ 87<br />
}<br />
mod97<br />
172 Multiplikation<br />
◮<br />
◮<br />
173 D = 10101101 B<br />
⇒ 87 173 mod 97 = 87 128+32+8+4+1 mod 97<br />
= 87 128 ⊙ 87 32 ⊙ 87 8 ⊙ 87 4 ⊙ 87 1 mod 97<br />
a 0 = 87<br />
a k+1 = a k ⊙ a k<br />
⇒ 87 173 mod 97 = a 0 ⊙ a 2 ⊙ a 3 ⊙ a 5 ⊙ a<br />
} {{ } 7<br />
10 Multiplikationen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 173 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 174 / 235<br />
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Modulorechnung für Potenzen – Programm<br />
typedef unsigned long long int unum;<br />
extern unum M;<br />
unum mprod(unum a, unum b) /* a * b */<br />
{<br />
return( ((a % M) * (b % M)) % M );<br />
}<br />
unum mpow(unum a, unum b) /* a ** b */<br />
{<br />
unum c = 1;<br />
a = a % M;<br />
while ( b ) {<br />
if ( b & 1 ) c = mprod(c, a);<br />
a = mprod(a, a); b >>= 1;<br />
}<br />
return c;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 175 / 235<br />
RSA – Schlüsselzusammenhang<br />
Kryptologie Kryptologie – Arithmetik großer Zahlen<br />
◮ Modul Z = (p − 1)(q − 1)<br />
◮ Schlüssel d geheim<br />
◮ öffentlicher Schlüssel e =?<br />
◮ e invers zu d bezüglich Modul Z<br />
◮ Erweiterter Euklidischer Algorithmus: xgcd()<br />
e d ≡ 1 (mod Z)<br />
1 ≡ gcd(Z, d)<br />
= x · Z + y · d<br />
(x, y) = xgcd(Z, d)<br />
⇒ e = y mod Z<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 176 / 235
Kryptologie<br />
Erweiterter Euklidischer Algorithmus<br />
g = gcd(a, b)<br />
Kryptologie – Arithmetik großer Zahlen<br />
g = x · a + y · b, (x, y) =?<br />
(x, y) = xgcd(a, b)<br />
r 0 = a = (s 0 = 1) · a + (t 0 = 0) · b<br />
r 1 = b = (s 1 = 0) · a + (t 1 = 1) · b q = ⌊r 0 /r 1 ⌋<br />
r 2 = r 0 − q r 1 =(s 2 = s 0 − q s 1 ) · a+(t 2 = t 0 − q t 1 ) · b q = ⌊r 1 /r 2 ⌋<br />
. . . . . .<br />
r n = 0=r n−2 − q r n−1 =(s n−2 − q s n−1 ) · a+(t n−2 − q t n−1 ) · b<br />
r n−1 = gcd(a, b) ⇒ x = s n−1 , y = t n−1<br />
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Erweiterter Euklidischer Algorithmus – Beispiel<br />
◮ Modul M = 31<br />
◮ bestimme das Inverse e zu d = 13!<br />
◮ (x, y) = xgcd(M, d)<br />
◮ e = y<br />
mod M<br />
i r i = M · s i + d · t i q = ⌊r i−1 /r i ⌋<br />
0 31= 31 · 1 + 13 · 0<br />
1 13= 31 · 0 + 13 · 1 2<br />
2 5 = 31 · 1 + 13 · −2 2<br />
3 3 =31 · −2+ 13 · 5 1<br />
4 2 = 31 · 3 + 13 · −7 1<br />
5 1 =31 · −5+ 13 · 12 2<br />
n = 6 0 = 31 · 13 +13 · −31<br />
⇒ e = t n−1 = 12 wegen 12 · 13 ≡ 1 (mod 31)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 177 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 178 / 235<br />
Kryptologie<br />
Kryptologie – Arithmetik großer Zahlen<br />
Erweiterter Euklidischer Algorithmus – Implementation<br />
Public Key – Anwendung<br />
Kryptologie<br />
Kryptologie – Anwendung<br />
int xgcd(int a, int b, int *x, int *y) {<br />
int r[2] = {a, b}, s[2] = {1, 0}, t[2] = {0, 1}, i, n;<br />
A<br />
M<br />
}<br />
for ( i = 0; r[n = !i]; i = n ) {<br />
int q = r[i] / r[n];<br />
r[i] -= q * r[n];<br />
s[i] -= q * s[n];<br />
t[i] -= q * t[n];<br />
}<br />
*x = s[i]; *y = t[i]; /* (x, y) = xgcd(a, b) */<br />
return r[i]; /* = gcd(a, b) */<br />
M<br />
S<br />
GS<br />
PS<br />
C<br />
GA<br />
PA<br />
E<br />
GE<br />
PE<br />
M<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 179 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 180 / 235
Kryptologie<br />
Kryptologie – Anwendung<br />
Geometrie<br />
Geometrische Objekte<br />
Public Key – RSA – Übung<br />
Koordinaten<br />
◮ Beispielzahlen p, q, d, e bestimmen/ermitteln,<br />
◮ Nachricht M erstellen und in Chiffre C verschlüsseln,<br />
◮ Chiffre C entschlüsseln.<br />
y<br />
r<br />
(x,y)<br />
◮ kartesisch: (x, y)<br />
◮ polar: (r, ϕ)<br />
◮ komplex:<br />
◮ z = x + i y = r e<br />
i ϕ<br />
◮ x = r cos ϕ, y = r sin ϕ<br />
ϕ<br />
x<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 181 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 182 / 235<br />
Geometrie<br />
Punkte, Strecken, Polygone<br />
Geometrische Objekte<br />
Geometrie<br />
Geometrische Objekte kodieren<br />
Geometrische Objekte<br />
A<br />
Punkt<br />
(x,y)<br />
Strecke<br />
P<br />
(x 1<br />
,y 1<br />
)<br />
A<br />
Q<br />
(x 2<br />
,y 2<br />
)<br />
F<br />
(x 1<br />
,y 1<br />
)<br />
B<br />
Rechteck<br />
(x 1<br />
,y 1<br />
)<br />
E<br />
D<br />
C<br />
Polygon<br />
A B<br />
(x 2<br />
,y 2<br />
)<br />
(x 2<br />
,y 2<br />
)<br />
◮ Koordinaten<br />
◮ Kennzeichen<br />
struct point { int x, int y; char c; };<br />
struct line { struct point p1, p2; };<br />
struct rect { struct point ul, or; };<br />
struct point polygon[N];<br />
typedef struct point point;<br />
typedef struct line line;<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 183 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 184 / 235
Geometrie<br />
Schnitt von Strecken<br />
Geometrie<br />
Schnitt von Strecken<br />
Schnitt von Strecken<br />
Orientierung von Strecken<br />
Funktion ccw(P0, P1, P2) (counter clockwise)<br />
D<br />
B<br />
P2<br />
◮ P 0 P 2 steiler als P 0 P 1<br />
⇒ ccw() = 1<br />
A<br />
C<br />
P0<br />
dx2<br />
ccw<br />
dy2<br />
dx1<br />
P1<br />
dy1<br />
◮ P 0 P 2 flacher als P 0 P 1<br />
⇒ ccw() = −1<br />
◮ P 0 , P 1 , P 2 kollinear:<br />
◮ P 0 → P 1 → P 2<br />
⇒ ccw() = 1<br />
◮ P 0 → P 2 → P 1<br />
⇒ ccw() = 0<br />
◮ P2 → P 0 → P 1<br />
⇒ ccw() = −1<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 185 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 186 / 235<br />
Geometrie<br />
Schnitt von Strecken<br />
Orientierung von Strecken – CCW(Implementierung)<br />
int ccw(point p0, point p1, point p2)<br />
{ /* P2 left to P0->P1 ? */<br />
int dx1, dx2, dy1, dy2;<br />
dx1 = p1.x - p0.x; dy1 = p1.y - p0.y;<br />
dx2 = p2.x - p0.x; dy2 = p2.y - p0.y;<br />
if ( dx1*dy2 > dy1*dx2 ) /* slope P0-P1, P0-P2 */<br />
return 1; /* left - ccw */<br />
if ( dx1*dy2 < dy1*dx2 )<br />
return -1; /* right */<br />
/* else collinear cases */<br />
if ((dx1*dx2 < 0) || (dy1*dy2 < 0))<br />
return -1; /* different directions from P0 */<br />
if ((dx1*dx1 + dy1*dy1) < (dx2*dx2 + dy2*dy2))<br />
return 1; /* P0 -> P1 -> P2 */<br />
return 0; /* P0 -> P2 -> P1 (P2 in between) */<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 187 / 235<br />
Schnitt von Strecken<br />
Strecken schneiden sich, wenn<br />
Geometrie<br />
Schnitt von Strecken<br />
◮ Enden der Strecke AB auf verschiedenen Seiten von CD und<br />
◮ Enden der Strecke CD auf verschiedenen Seiten von AB<br />
int intersect(line l1, line l2)<br />
{<br />
return ( ((ccw(l1.p1, l1.p2, l2.p1)<br />
* ccw(l1.p1, l1.p2, l2.p2))
Geometrie<br />
Einfacher geschlossener Pfad<br />
Polygon<br />
Geometrie<br />
Polygon<br />
Einfacher geschlossener Pfad – Algorithmus<br />
◮ gegeben: Punktemenge P i<br />
◮ gesucht: Linienzug, der<br />
◮ alle Punkte erreicht<br />
◮ sich selbst nicht schneidet<br />
1. wähle einen (innenliegenden) Punkt als Anker A (Ursprung)<br />
2. berechne Winkel α i zwischen Abszisse und A P i<br />
3. sortiere Punkte nach aufsteigendem Winkel<br />
4. verbinde die sortierten Punkte<br />
Aufwand: A =?<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 189 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 190 / 235<br />
Geometrie<br />
Polygon<br />
Einfacher geschlossener Pfad – Ablauf<br />
Geometrie<br />
Polygon<br />
Einfacher geschlossener Pfad – Winkel<br />
M<br />
4<br />
J<br />
α i = atan2(∆y, ∆x)<br />
C<br />
I<br />
H<br />
N<br />
E<br />
B<br />
K<br />
A<br />
F<br />
G<br />
3<br />
L<br />
2<br />
D<br />
1<br />
0<br />
double a(point p1, point p2)<br />
{<br />
/* use if math is fast */<br />
int dx, dy;<br />
dx = p2.x - p1.x;<br />
dy = p2.y - p1.y;<br />
return atan2(dy, dx);<br />
/* radians */<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 191 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 192 / 235
Enthaltensein in Polygon<br />
Geometrie<br />
Polygon<br />
Geometrie<br />
Polygon<br />
Enthaltensein in Polygon – Umlauf<br />
◮ Polygon P i , i = 1 . . . n<br />
◮ Punkt A in Polygon?<br />
◮ Testlinie von außen bis A<br />
◮ Anzahl Schnitte ⇒ innen/außen?<br />
A<br />
A<br />
1. Testlinie −∞ → A<br />
2. laufe um Polygon<br />
3. ignoriere P i auf Testlinie<br />
4. zähle Schnitte m<br />
5. m ungerade ⇒ A innen<br />
P1<br />
Pn<br />
P2<br />
P3<br />
P4<br />
A<br />
A<br />
A<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 193 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 194 / 235<br />
Geometrie<br />
Polygon<br />
Geometrie<br />
Polygon<br />
Enthaltensein in Polygon – Implementation<br />
Enthaltensein in Polygon (einfach, konvex)<br />
int inside(point A, point p[], int N)<br />
{<br />
int i, j = 0, cnt = 0; /* j: last point not on test line*/<br />
line lt, lp; /* lt: test line, lp: intersection line */<br />
p[0] = p[N]; p[N + 1] = p[1]; /* close polygon */<br />
lt.p1 = lt.p2 = A;<br />
lt.p1.x = -INT_MAX; /* test line starts far away */<br />
for ( i = 1; i
Geometrie<br />
Polygon<br />
Geometrie<br />
Polygon<br />
Konvexe Hülle<br />
Konvexe Hülle – Einwickeln<br />
1. Punkte P i , i = 1 . . . n<br />
2. (außenliegender) Ankerpunkt A<br />
3. A P i : Winkel α i<br />
4. α min : Linie<br />
A = O(n 2 )<br />
I<br />
H<br />
J<br />
K<br />
L<br />
O<br />
G<br />
F<br />
M<br />
N<br />
E<br />
C<br />
A<br />
D<br />
B<br />
I<br />
H<br />
J<br />
K<br />
L<br />
O<br />
G<br />
F<br />
M<br />
N<br />
E<br />
C<br />
A<br />
D<br />
B<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 197 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 198 / 235<br />
Geometrie<br />
Polygon<br />
Konvexe Hülle – Einwickeln: Implementation<br />
int wrap(struct point p[], int N)<br />
{<br />
int i = 1, min, M; double th, th0, al; point t;<br />
for (min = 0; i < N; i++)<br />
if (p[i].y < p[min].y) min = i;<br />
p[N] = p[min]; th = 0.0;<br />
for (M = 0; M < N; M++) {<br />
swap(p[M], p[min]); min = N; th0 = th; th = 360.0;<br />
for (i = M + 1; i
Geometrie<br />
Polygon<br />
Geometrie<br />
Polygon<br />
Konvexe Hülle – Graham(Ablauf)<br />
Konvexe Hülle – Graham: Implementation<br />
A<br />
E<br />
C<br />
D<br />
B<br />
int grahamscan(point p[], int N)<br />
{<br />
int i, min, M;<br />
point t;<br />
for (min = 1, i = 2; i
Geometrie<br />
Polygonfläche – Berechnung<br />
Polygon<br />
Geometrie<br />
Polygonfläche – Implementation<br />
Polygon<br />
∑n−1<br />
2A = 2 a i =<br />
i=0<br />
=<br />
=<br />
=<br />
=<br />
∑n−1<br />
x i y i+1 − x i+1 y i<br />
i=0<br />
n−1<br />
∑<br />
x i y i+1 −<br />
i=0<br />
n∑<br />
x i y i+1 −<br />
i=1<br />
n∑<br />
x i y i−1<br />
i=1<br />
n∑<br />
x i y i−1 , P n+1 = P 1<br />
i=1<br />
n∑<br />
x i y i+1 − x i y i−1<br />
i=1<br />
n∑<br />
x i (y i+1 − y i−1 )<br />
i=1<br />
double pgarea(point p[], int n)<br />
{<br />
double a; /* area */<br />
int i;<br />
}<br />
/* initialize area - avoid modulo operation */<br />
a = p[0].x * (p[1].y - p[n-1].y) +<br />
p[n-1].x * (p[0].y - p[n-2].y);<br />
for ( i = 1; i < n-1; i ++ ) {<br />
a += p[i].x * (p[i+1].y - p[i-1].y);<br />
}<br />
a = ( a < 0 ) ? (-a) : a; /* area positive */<br />
return(a/2);<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 205 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 206 / 235<br />
Geometrie<br />
Schnelles Zeichnen – Kreis<br />
Geometrie<br />
Schnelles Zeichnen – Kreis<br />
Kreis im Raster<br />
Kreis im Raster – Trigonometrie<br />
y<br />
45°<br />
ϕ<br />
r<br />
(x,y)<br />
x<br />
y = √ r 2 − x 2<br />
x = r cos ϕ<br />
y = r sin ϕ<br />
◮ Raster-Einheit: 1 Pixel<br />
◮ Symmetrie im Kreis<br />
void trigo(int r)<br />
{<br />
double pi4, phi, rad, x, y;<br />
int i, n;<br />
pi4 = atan(1.0); /* pi/4 */<br />
rad = (double) abs(r);<br />
n = rnd(rad * pi4); /* pixels */<br />
for ( i = 0; i < n; i ++ ) {<br />
phi = (pi4 * i) / n;<br />
x = rad * sin(phi);<br />
y = rad * cos(phi);<br />
plot(r, rnd(x), rnd(y));<br />
}<br />
}<br />
int rnd(double x) {<br />
/* round to */<br />
/* nearest int */<br />
int s = 1, r;<br />
if ( x < 0 ) {<br />
x = -x;<br />
s = -1;<br />
}<br />
r = (int) (x+0.5);<br />
return (s * r);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 207 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 208 / 235
Geometrie<br />
Schnelles Zeichnen – Kreis<br />
Geometrie<br />
Schnelles Zeichnen – Kreis<br />
Kreis im Raster – Wurzel<br />
Kreis im Raster – Bresenham<br />
y<br />
void wurzel(int r)<br />
{<br />
double x, y, yh, r2;<br />
yh = abs(r) / sqrt(2.0);<br />
r2 = (double) (r * r);<br />
for ( y = 0.0; y 0 ⇒ y → y − 1<br />
Geometrie<br />
Schnelles Zeichnen – Kreis<br />
Kreis im Raster – Bresenham(Implementation)<br />
void bresenham(int r)<br />
{<br />
int x = 0, y, f = 0;<br />
y = abs(r); /* start at top */<br />
while (x < y) {<br />
plot(r, x, y); /* show pixel */<br />
++ x; /* next pixel right */<br />
if (f < 0) { /* edge inside circle? */<br />
f += 2*x - 1; /* yes, move right */<br />
} else {<br />
f += 2*(x - y); /* no */<br />
--y; /* move down */<br />
}<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 211 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 212 / 235
Graphen<br />
Graphen<br />
Datenstrukturen<br />
Graphen<br />
Graphen – Datenstrukturen<br />
F<br />
M<br />
D<br />
E<br />
N<br />
1 2<br />
1<br />
2<br />
L<br />
O<br />
A<br />
G<br />
ungerichtet<br />
K<br />
J<br />
C<br />
B<br />
H<br />
I<br />
◮ (un-)gerichtet<br />
◮ (un-)gewichtet<br />
◮ licht/dicht<br />
◮ (a-)zyklisch<br />
◮ V Knoten<br />
◮ E Kanten<br />
◮ Pfad<br />
◮ Graph/Baum<br />
◮ Zusammenhang<br />
◮ Spannbaum<br />
Adjazenzmatrix<br />
ungerichtet<br />
A B C D E F G<br />
A 1 1 1 0 0 1 1<br />
B 1 1 0 0 0 0 0<br />
C 1 0 1 0 0 0 0<br />
D 0 0 0 1 1 1 0<br />
E 0 0 0 1 1 1 1<br />
F 1 0 0 1 1 1 0<br />
G 1 0 0 0 1 0 1<br />
gerichtet<br />
H I J K<br />
H 0 1 1 1<br />
I 0 0 0 0<br />
J 0 0 0 1<br />
K 0 0 0 0<br />
gewichtet<br />
L M N O<br />
L 1 1 0 2<br />
M 1 1 1 0<br />
N 0 1 1 2<br />
O 2 0 2 1<br />
gewichtet<br />
gerichtet<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 213 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 214 / 235<br />
Graphen<br />
Datenstrukturen<br />
Graphen<br />
Datenstrukturen<br />
Graphen – Datenstrukturen<br />
Adjazenzstruktur zu 1)<br />
Liste der Nachbarn<br />
#define Vmax 256<br />
struct nb {<br />
int c, w;<br />
struct nb *next;<br />
};<br />
typedef struct nb nb;<br />
nb *alist[Vmax];<br />
A<br />
B<br />
C<br />
F<br />
G<br />
B<br />
A<br />
C<br />
A<br />
D<br />
E<br />
F<br />
E<br />
D<br />
F<br />
G<br />
F<br />
A<br />
D<br />
E<br />
G<br />
A<br />
E<br />
Graphen – Visualisierung<br />
Beispiel zu 1) mit Graphviz (http://www.graphviz.org)<br />
digraph undir {<br />
fontname=Helvetica;<br />
label = "ungerichtet";<br />
splines = false;<br />
color = none;<br />
edge [arrowhead=none, fontname=Helvetica];<br />
node [shape=circle, width=0.3, fontname=Helvetica];<br />
A -> { B C G };<br />
A -> F [minlen=3];<br />
D -> { E F};<br />
E -> { F G};<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 215 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 216 / 235
Graphen<br />
Graphen – Traversierung/Suche<br />
Graphen – Suche<br />
Graphen<br />
Graphen – Tiefensuche(rekursiv)<br />
Graphen – Suche<br />
int id;<br />
void dfs()<br />
{<br />
node *v;<br />
id = 0;<br />
for (v = fstnode(); v != NULL; v = nxtnode(v)) {<br />
if ( unseen(v) ) {<br />
visit(v);<br />
}<br />
}<br />
}<br />
void visit(node *v)<br />
{<br />
edge *e;<br />
node *t;<br />
}<br />
mark(v, ++id);<br />
for (e = fstout(v); e != NULL; e = nxtout(e)) {<br />
t = e->head;<br />
if ( unseen(t) ) {<br />
visit(t);<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 217 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 218 / 235<br />
Graphen Graphen – Suche<br />
Graphen – Verlauf Tiefensuche (rekursiv)<br />
l<br />
k<br />
q<br />
i<br />
r<br />
n<br />
t<br />
h<br />
j<br />
u<br />
s<br />
e<br />
g<br />
f<br />
v<br />
d<br />
w<br />
z<br />
a<br />
x<br />
b<br />
c<br />
y<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 219 / 235<br />
Graphen<br />
Graphen – Suche<br />
Graphen – Tiefen-/Breitensuche(iterativ)<br />
traverse()<br />
{<br />
node *v;<br />
for (v = fstnode(); v != NULL; v = nxtnode(v)) {<br />
if ( unseen(v) ) {<br />
visit(v);<br />
}<br />
}<br />
}<br />
int dfs()<br />
{<br />
stack_init();<br />
empty = stackempty;<br />
insert = push;<br />
extract = pop;<br />
traverse();<br />
}<br />
int bfs()<br />
{<br />
strcpy(method, "bfs");<br />
queue_init();<br />
empty = queueempty;<br />
insert = put;<br />
extract = get;<br />
traverse();<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 220 / 235
Graphen<br />
Graphen – Suche<br />
Graphen<br />
Graphen – Suche<br />
Graphen – Traversierung Tiefen-/Breitensuche<br />
void visit(node *v)<br />
{<br />
edge *e;<br />
node *t;<br />
id = 0;<br />
insert(v);<br />
while ( !empty() ) {<br />
v = extract();<br />
mark(v, ++id);<br />
for (e = fstout(v); e != NULL; e = nxtout(e)) {<br />
t = e->head;<br />
if ( unseen(t) ) {<br />
insert(t);<br />
mark(t, -1);<br />
}<br />
}<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 221 / 235<br />
Graphen – Tiefensuche Verlauf (iterativ per Stack)<br />
l<br />
k<br />
q<br />
i<br />
r<br />
n<br />
t<br />
h<br />
j<br />
u<br />
s<br />
e<br />
g<br />
f<br />
v<br />
d<br />
w<br />
z<br />
a<br />
x<br />
b<br />
c<br />
y<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 222 / 235<br />
Graphen<br />
Graphen – Suche<br />
Graphen<br />
Graphen – Suche<br />
Graphen – Breitensuche Verlauf (per Queue)<br />
Graphen – Tiefen-/Breitensuche Vergleich<br />
k<br />
l<br />
h<br />
i<br />
j<br />
q<br />
r<br />
n<br />
t<br />
◮ Tiefensuche: Bestimmung der Pfadlängen<br />
◮ Breitensuche: Bestimmung kürzester Pfade<br />
e<br />
f<br />
g<br />
d<br />
s<br />
u<br />
v<br />
a<br />
b<br />
c<br />
z<br />
w<br />
x<br />
y<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 223 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 224 / 235
Graphen<br />
Graphen – Suche<br />
Graphen<br />
Graphen – Suche<br />
Graphentraversierung – Aufwand<br />
Graphen – Zusammenhang<br />
◮ Adjazenzmatrix: A = O(n 2 )<br />
◮ Adjazenzstruktur: A = O(n)<br />
int traverse()<br />
{<br />
node *v;<br />
int n = 0;<br />
for (v = fstnode(); v != NULL; v = nxtnode(v)) {<br />
if ( unseen(v) ) {<br />
visit(v);<br />
n ++;<br />
}<br />
}<br />
return n;<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 225 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 226 / 235<br />
Graphen<br />
Graphen – Suche<br />
Graphen<br />
Graphen – Suche<br />
Graphen – Zyklen<br />
Graphen – Topologisches Sortieren<br />
◮ zusammenhängender Graph<br />
◮ zyklenfrei: jeder Knoten ist Kantenende (Ausnahme: Wurzel)<br />
◮ V − E = 1 ⇒ zyklenfrei<br />
◮ V = E ⇒ ein Zyklus<br />
◮ E − V = n ⇒ n + 1 Zyklen<br />
◮ DAG (directed, acyclic<br />
graph)<br />
◮ Topologische Sortierung:<br />
A B F E D J K L M G C H I<br />
◮ Tiefensuche mit<br />
umgekehrter Richtung<br />
→ umgekehrte<br />
topologische Sortierung<br />
E<br />
D<br />
F<br />
A<br />
C<br />
B<br />
H<br />
G<br />
L<br />
J<br />
M<br />
K<br />
I<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 227 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 228 / 235
Graphen – Kürzeste Pfade<br />
Graphen Graphen – kürzeste Pfade<br />
◮ gegeben: Netz aus Knoten mit gewichteten Kanten<br />
◮ gesucht: die kürzesten Wege im Netz<br />
◮ Anwendung:<br />
◮ Transport<br />
◮ Netzwerktechnik (Routing: OSPF)<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 229 / 235<br />
Graphen<br />
Graphen – kürzeste Pfade<br />
1: procedure ShortestPath(Graph, start):<br />
2: for all v ∈ Graph do<br />
3: dist(v) ← ∞, pre(v) ← 0<br />
4: end for<br />
5: dist(start) ← 0, Q ← v ∈ Graph<br />
6: while |Q| > 0 do<br />
7: u ← v ∈ Q, dist(v) = min<br />
8: if dist(u) < ∞ then<br />
9: remove(u) from Q<br />
10: for all v ∈ Neighbour(u) do<br />
11: d ← dist(u) + dist(u, v)<br />
12: if d < dist(v) then<br />
13: dist(v) ← d, pre(v) ← u<br />
14: end if<br />
15: end for<br />
16: end if<br />
17: end while<br />
18: end procedure<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 230 / 235<br />
Graphen<br />
Graphen – kürzeste Pfade<br />
Graphen – Kürzeste Pfade/Prioritätssuche<br />
#define unseen -(INT_MAX - 1)<br />
int dist[Vmax], pre[Vmax], id = 0;<br />
listpfs()<br />
{<br />
int k;<br />
pqinitialize();<br />
for ( k = 0; k < N; k++ )<br />
dist[k] = -unseen;<br />
for ( k = 0; k < N; k++ )<br />
if ( dist[k] == -unseen )<br />
visit(idx[k]);<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 231 / 235<br />
Graphen<br />
Graphen – kürzeste Pfade<br />
Graphen – Kürzeste Pfade/Traversierung<br />
void visit(int k)<br />
{<br />
struct node *t; int prio;<br />
if (pqupdate(k, unseen) != 0) pre[k] = 0;<br />
while (!pqempty()) {<br />
id++; k = pqremove(); dist[k] = -dist[k];<br />
if (dist[k] == unseen) dist[k] = 0;<br />
for (t = alist[k]; t != t->next; t = t->next) {<br />
if (dist[t->c] < 0) {<br />
if (pqupdate(t->c, prio = dist[k]+t->w)) {<br />
dist[t->c] = -prio; pre[t->c] = k;<br />
}<br />
}<br />
}<br />
}<br />
}<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 232 / 235
Graphen<br />
Graphen – kürzeste Pfade<br />
Graphen – Kürzeste Pfade/Implementation<br />
Schwierige Probleme<br />
Weiterführende Themen<br />
Schwierige Probleme<br />
◮ Prioritätswarteschlange: Heap<br />
◮ A = O((E + V ) log V )<br />
◮ Analogie zu Tiefen-/Breitensuche<br />
◮<br />
Ähnliche Probleme: z.B. minimaler Spannbaum<br />
◮ Aufwand steigt stärker als polynomial<br />
◮ Beispiele:<br />
◮ Handelsreisendenproblem<br />
◮ Rucksackproblem<br />
◮ Aussagenlogik (Cook)<br />
◮ diophantische Gleichungen<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 233 / 235<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 234 / 235<br />
NP-Vollständigkeit<br />
Weiterführende Themen<br />
NP-Vollständigkeit<br />
◮ Klasseneinteilung Probleme:<br />
P: können mit deterministischen Automaten in<br />
polynomialer Zeit gelöst werden<br />
NP: können mit nondeterministischen Automaten in<br />
polynomialer Zeit gelöst werden<br />
NP-vollständig: eines lösbar ⇒ alle lösbar<br />
◮ Nondeterministischer Automat<br />
◮ Ungelöst: P = NP?<br />
◮ Approximation<br />
Prof. Dr.-Ing. <strong>Torsten</strong> <strong>Finke</strong> (FOM) Algorithmen 2013-12-01 235 / 235