Sie sind auf Seite 1von 151

Computerorientierte Mathematik II mit Java

Rolf H. M hring o
Technische Universit t Berlin a Institut f r Mathematik u

Sommersemester 2005

ii

Vorbemerkungen
Diese Vorlesung ist der zweite Teil des Zyklus Computerorientierte Mathematik und schliet sich direkt an die Computerorientierte Mathematik I an. Dieses Skript basiert auf meiner Vorlesung vom Sommersemester 2004. Zwei Studenten der Vorlesung, Elisabeth G nther und Olaf Maurer, haben u im Sommer 2004 eine ausgezeichnete Ausarbeitung der Vorlesung angefertigt, die von mir nur noch leicht uberarbeitet und erg nzt wurde. Das Resultat ist dieses Skript, das auch online unter a http://www.math.tu-berlin.de/coga/moehring/Coma/Skript-II-Java/ zur Verf gung steht. u Die Vorlesung umfasst folgende Punkte: Wir behandeln zun chst ein Sortierverfahren namens Bucketa sort, das durch besondere Anforderungen an die Schl sselmenge schon in linearer Zeit sortieren kann. u Dann werden B ume, insbesondere bin re B ume besprochen und wie diese zur Datenkompression a a a mit dem Huffman-Algorithmus genutzt werden k nnen. B ume nden als Suchb ume und insbesono a a dere als AVL-B ume weitere Verwendung. Wir kommen dann zu optimalen statischen Suchb umen a a und besprechen eine Alternative zum Suchen in B umen, das sogenannte Hashing. Den Abschluss a des Semesters bildet ein Kapitel uber Schaltkreistheorie und Programmierbare Logische Arrays.

iii

iv

VORBEMERKUNGEN

Inhaltsverzeichnis
Vorbemerkungen Inhaltsverzeichnis 1 Bucketsort 1.1 Einfaches Bucketsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 1.1.2 1.1.3 1.2 Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Aufwandsanalyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii v 1 2 2 4 4 5 6 8 9 13 15 15 15 17 22 25 26 27 29 v

Sortieren von Strings mit Bucketsort . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1 1.2.2 1.2.3 Sortieren von Strings der L nge k . . . . . . . . . . . . . . . . . . . . . . . a Sortieren von Bin rzahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . a Sortieren von Strings variabler L nge . . . . . . . . . . . . . . . . . . . . . a

1.3 2

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

B ume und Priority Queues a 2.1 B ume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 2.1.1 2.1.2 2.1.3 2.2 Grundbegriffe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Implementation von bin ren B umen . . . . . . . . . . . . . . . . . . . . . a a Traversierung von B umen . . . . . . . . . . . . . . . . . . . . . . . . . . . a

Priority Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 M gliche Implementationen einer Priority Queue . . . . . . . . . . . . . . . o

2.3 3

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Huffman Codes und Datenkompression

vi 3.1

INHALTSVERZEICHNIS Codierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 3.2 3.3 Pr xcode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 29 31 33 41 41 41 41 43 44 45 46 46 46 46 51 53 53 57 61 62 62 65 67 69 69 70 73 81 83 83

Der Huffman Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Weitere Datenkompressionsverfahren . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 3.3.2 3.3.3 Der adaptive Huffmancode . . . . . . . . . . . . . . . . . . . . . . . . . . . Der run length code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Der Lempel-Ziv Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.4 3.5 4

Abschlieende Bemerkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Suchb ume a 4.1 Basisoperationen in Suchb umen . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 4.1.1 4.1.2 4.1.3 4.2 Suchen nach Schl ssel k . . . . . . . . . . . . . . . . . . . . . . . . . . . . u Einf gen eines Knoten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u L schen eines Knoten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

AVL-B ume a 5.1 5.2 5.3 Grunds tzliche Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a Rotationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Die Basisoperationen in AVL-B umen . . . . . . . . . . . . . . . . . . . . . . . . . a 5.3.1 5.3.2 5.3.3 5.4 Suchen eines Knotens v . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einf gen eines neuen Knotens v . . . . . . . . . . . . . . . . . . . . . . . . u L schen eines Knotens v . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Optimale statische Suchb ume a 6.1 6.2 6.3 6.4 Statische Suchb ume allgemein . . . . . . . . . . . . . . . . . . . . . . . . . . . . a Optimalit t statischer Suchb ume . . . . . . . . . . . . . . . . . . . . . . . . . . . a a Konstruktion eines optimalen statischen Suchbaumes . . . . . . . . . . . . . . . . . Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

B-B ume a 7.1 Denition und Eigenschaften . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

INHALTSVERZEICHNIS 7.2 Basisoperationen in B-B umen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 7.2.1 7.2.2 7.2.3 7.3 8 Suchen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Einf gen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u L schen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . o

vii 86 86 86 88 91 93 94 95 95 96 96 97

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Hashing 8.1 Hash-Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 8.1.2 8.2 8.2.1 8.2.2 8.3 Divisionsmethode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multiplikationsmethode . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chaining . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Offene Adressierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Kollisionsbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 107

Schaltkreistheorie und Rechnerarchitektur 9.1 9.2

Schaltfunktionen und Schaltnetze . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Vereinfachung von Schaltnetzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 9.2.1 9.2.2 9.2.3 Das Verfahren von Karnaugh . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Das Verfahren von Quine und McCluskey . . . . . . . . . . . . . . . . . . . 120 Das Uberdeckungsproblem . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Addierwerke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Das Fan-In-Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Aufbau eines PLAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Zur Programmierung von PLAs . . . . . . . . . . . . . . . . . . . . . . . . 133

9.3

Schaltungen mit Delays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 9.3.1 9.3.2

9.4

PLAs und das Prinzip der Mikroprogrammierung . . . . . . . . . . . . . . . . . . . 131 9.4.1 9.4.2

9.5

Literaturhinweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 141 142

Literaturverzeichnis Index

viii

INHALTSVERZEICHNIS

Kapitel 1

Bucketsort
Bucketsort ist ein Sortierverfahren, das grunds tzlich anders als alle Sortierverfahren funktioniert, die a wir bisher kennen gelernt haben. Es zeichnet sich dadurch aus, dass es nicht wie die Verfahren aus Teil I der Vorlesung auf paarweisen Vergleichen von Schl sseln basiert, sondern voraussetzt, dass u die Schl sselmenge klein und bekannt ist, und dass es Objekte direkt dem richtigen Bucket (Fach) u zuordnet. Anschaulich l sst sich dieses Verfahren mit der Verteilung der Post im Postamt auf die H user einer a a Strae vergleichen. Der Brieftr ger hat eine Reihe von F chern, die den Hausnummern entsprechen. a a Er geht die Briefe der Reihe nach durch und legt jeden Brief in O(1) (also konstanter) Zeit in das Fach mit der entsprechenden Hausnummer. Dabei k nnen in einem Fach nat rlich mehrere Briefe sein, die o u aber aus Sicht der Ordnungsrelation gleich sind (da sie in das gleiche Bucket sortiert werden, haben sie ja die gleiche Nummer) und daher nicht mehr innerhalb des Fachs sortiert werden m ssen. Der u Brieftr ger entnimmt die Briefe den F chern der Reihe nach und hat sie damit nach Hausnummern a a sortiert. Bei m Hausnummern und n Briefen sortiert er also in O(m + n). Da in der Regel m n gilt, wenn Bucketsort angewendet wird, bendet sich der Algorithmus dann in der Komplexit tsordnung (2n) = a (n) und man erh lt so also einen Sortieralgorithmus, dessen Aufwand linear von der Anzahl der zu a sortierenden Schl ssel abh ngt. u a Man beachte, dass die in der CoMa I ermittelte untere Komplexit tsschranke von (n log n) nur a Sortieralgorithmen betrifft, die auf paarweisen Vergleichen beruhen. Bucketsort beruht jedoch nicht auf paarweisen Vergleichen von Schl sseln und setzt auerdem zus tzliche Informationen uber die u a Schl sselmenge voraus. Daher liegt Bucketsort nicht in der Klasse der Sortieralgorithmen, die von u dieser Schranke betroffen sind. Umgesetzt auf Datenstrukturen bedeutet dies:

Version vom 24. M rz 2006 a

2 Wirklichkeit F cher a Hausnummern Stapel im Fach Briefe am Anfang Briefe am Ende

KAPITEL 1. BUCKETSORT Datenstruktur Array Array-Indizes Liste an jedem Array-Index Liste Liste

1.1
1.1.1

Einfaches Bucketsort
Denition

Wir geben jetzt einen Algorithmus f r die oben erkl rte Situation an. Gegeben seien also n Obu a jekte a1 , a2 , . . . , an mit Schl sselwerten s(a1 ), s(a2 ), . . . , s(an ) in einer Liste L. O.B.d.A. seien die u Schl sselwerte Zahlen zwischen 0 und m 1, also s(a j ) {0, 1, . . . , m 1}, j = 1, . . . , n. Es gibt u dann also genau m paarweise verschiedene Schl sselwerte. u Algorithmus 1.1 (Einfaches Bucketsort) 1. Initialisiere ein Array mit m leeren Queues Qi (Buckets), je eine f r jeden Wert i = 0, 1, . . . , m1 u und je einer Referenz (head bzw. tail) auf den Anfang und das Ende der Queue Qi . 2. Durchlaufe L und f ge das Objekt a j entsprechend seines Schl sselwertes in die Queue Qs(a j ) u u ein. 3. Konkateniere die Queues Q0 , Q1 , . . . , Qm1 uber die head- und tail-Referenzen zu einer Liste L und gebe L zur ck. u Beispiel 1.1 Sei m = 5 und n = 9. Die Liste L ist gegeben durch Abbildung 1.1.
head r E a1 E a2 E a3 E a4 E a5 E a6 E a7 E a8 E a9

Abbildung 1.1: Liste L der zu sortierenden Elemente Es wird ein Array A mit je 2 Referenzen auf head und tail der Queues Qi eingerichtet. Abbildung 1.2 zeigt die Queues nach Abarbeitung der Liste L, also am Ende von Schritt 2. Dann werden die einzelnen Listen konkateniert. Das Konkatenieren der Listen ist sehr einfach, da nur das letzte Element ( ber tail) auf das erste Element ( ber head) der n chsten nichtleeren Liste gesetzt u u a werden muss, siehe Abbildung 1.3.

1.1. EINFACHES BUCKETSORT

A
r E a3 E a7

A[0] A[1] A[2] A[3] A[4]

0
r r r r r r r r r

r r r

E a2 E a9

r r

E a1 E a4 E a5

E a6 E a8

Abbildung 1.2: Queues nach Abarbeitung der Liste

A
r E a3 E a7

A[0] A[1] A[2] A[3] A[4]

0
r r r r r r r r r

r r r

r r r

E a2 E a9

E a1 E a4 E a5

E a6 E a8

Abbildung 1.3: Queues nach Konkatenation der Einzellisten

KAPITEL 1. BUCKETSORT

1.1.2

Implementation

Eine Implementation in Java k nnte in etwa wie folgt aussehen: o class QueuePointer { public ListNode head; public ListNode tail; } QueuePointer[] A = new QueuePointer[n]; // array with head- and tail-reference in each field Das Einf gen des Knoten node mit Schl sselwert i in die i-te Queue Qi geschieht dann mit einer u u Anweisung der Form A[i].tail.setNext(node); Die Konkatenation zweier Queues erfolgt uber die Anweisung A[i].tail.setNext(A[j].head); Dabei ist j die erste nichtleere Liste nach i.

1.1.3

Aufwandsanalyse

Satz 1.1 (Aufwand von einfachem Bucketsort) Algorithmus 1.1 sortiert die Liste korrekt in O(m + n) Zeit. Beweis: Am Ende von Schritt 2 enth lt jede Queue Qi nur Objekte a j mit Schl ssel s(a j ) = i. Die a u Konkatenation der Queues in der Reihenfolge Q0 , Q1 , . . . , Qm1 liefert also eine korrekt sortierte Liste. Das Einf gen von a j in die Queue Qi mit i = s(a j ) erfolgt durch Umh ngen von Referenzen in O(1) u a Zeit. Beim Durchlaufen der Liste L sind alle Vorg nger von a j bereits aus L entfernt und der Listena zeiger current der Liste L zeigt auf a j . Die Sequenz A[i].tail.setNext(current); A[i].tail = current; current = current.getNext(); h ngt a j aus L aus und in Qi ein. Das Einf gen aller Objekte a j geschieht also in O(n) Zeit. a u Das Konkatenieren der Queues kann in einer Schleife mit O(1) Aufwand pro Queue geschehen. Wir geben ein Code-Fragment an, das die Konkatenierung durchf hrt: u

1.2. SORTIEREN VON STRINGS MIT BUCKETSORT k = 0; while ((A[k].head == NULL) && (k < m)) k++; // k is now the first nonempty list in A, if there is one i = k + 1; while (i < m) { // while-loop: O(m) // at this point k is the last list we have already concatenated // we will now look for the next nonempty list after k while ((A[i].head == NULL) && (i < m)) i++; if (i==m) break; // if (i==m), we have iterated through all nonempty lists // in A and are finished // we have found a new nonempty list, concatenate it to k A[k].tail.setNext(A[i].head); // and prepare k for the next iteration k = i; i++; } // endwhile

Weil das Konkatenieren pro Queue nur einen Aufwand in O(1) ben tigt und maximal m Buckets kono kateniert werden m ssen, ist der Aufwand damit insgesamt O(n) + O(m) = O(m + n). u

Falls m n gilt, ist der Aufwand in der Komplexit tsklasse O(n). Bucketsort schl gt dann also die a a untere Komplexit tsschranke f r Sortieralgorithmen, die auf paarweisen Vergleichen beruhen. Daf r a u u ben tigt Bucketsort allerdings Informationen uber die Werte der auftretenden Schl ssel, weil sonst o u m nicht klein gehalten werden kann und der Aufwand von Bucketsort nur dann in O(n) liegt, wenn m n gilt.

1.2

Sortieren von Strings mit Bucketsort

Wir wollen jetzt Bucketsort zum Sortieren von Strings gem der lexikographischen Ordnung nutzen. a Wir denieren zuerst, was wir unter lexikographisch kleiner verstehen wollen: Sei S die Menge der Zeichen und eine lineare Ordnung auf S. Seien A = a1 a2 . . . a p und B = b1 b2 . . . bq zwei Strings der L nge p bzw. q uber S. Dann heit A lexikographisch kleiner als B, in a Zeichen A lex B

6 falls einer der folgenden F lle zutrifft: a

KAPITEL 1. BUCKETSORT

1. p q und ai = bi f r i = 1, . . . , p (d.h. A ist ein Anfangsst ck von B). u u 2. Es gibt j {1, . . . , p} mit a j b j und ai = bi f r i = 1, . . . , j 1 (d.h. an der ersten Stelle j, an u der A und B verschieden sind, ist a j kleiner oder gleich b j bez glich der linearen Ordnung auf u S). Beispiel 1.2 Hall lex Hallo, Arbeit lex Album

Wir sortieren mit Bucketsort lexikographisch, indem wir f r jede Komponente einfaches Bucketsort u verwenden. Zun chst betrachten wir den Spezialfall, dass alle Strings die gleiche L nge k haben. Dies a a beinhaltet insbesondere das Sortieren k-stelliger Bin rzahlen beziehungsweise von Strings auf der a Zeichenmenge Sb = {0, 1}.

1.2.1

Sortieren von Strings der L nge k a

Die Idee besteht darin, die Strings bez glich der Stellen mit Bucketsort zu sortieren, wobei die Stelu len von hinten nach vorn durchlaufen werden. Dies gew hrleistet, dass vor dem Bucketsort bez glich a u Stelle i (also nach k i Iterationen) die Strings bereits nach den letzten Stellen i + 1, . . . , k lexikographisch sortiert sind. Diese Sortierung wird trotz der sp teren Durchl ufe erhalten, weil durch Bucketsa a ort die Elemente, die an einer Stelle i gleich sind, in der gleichen Reihenfolge eingef gt werden, in der u sie schon waren (durch die vorherige Iteration beziehungsweise von Anfang an). Diese Eigenschaft eines Sortieralgorithmus bezeichnet man als Stabilit t, Bucketsort ist ein stabiler Sortieralgorithmus. a

Algorithmus 1.2 (Bucketsort) Input: Eine Liste L mit Strings A1 , A2 , . . . , An der L nge k mit Ai = ai1 , ai2 , . . . , aik und ai j S = a {0, 1, . . . , m 1} Output: Eine Permutation B1 , . . . , Bn von A1 , . . . , An mit Bi lex B2 lex lex Bn Methode: 1. Richte eine Queue Q ein und f ge A1 , . . . , An in Q ein. 1 u 2. Richte ein Array Bucket von m Buckets ein (wie beim einfachen Bucketsort) 3. for jede Stelle r := k downto 1 do 3.1 Leere alle Buckets Bucket[i] 3.2 while Q nicht leer ist do
1 Einf gen bedeutet hier immer, dass nur Referenzen auf A eingef gt werden. Das Einf gen geschieht also in O(1) und u u u i nicht wie beim zeichenweisen Einf gen des Strings in O(k). u

1.2. SORTIEREN VON STRINGS MIT BUCKETSORT Sei A j das erste Element in Q Entferne A j aus Q und f ge es in Bucket[i] mit i = a jr ein u endwhile 3.3 Konkateniere die nichtleeren Buckets in die Queue Q endfor Beispiel 1.3 Sei S = {0, 1} und 0 < 1. Seien A1 = 010, A2 = 011, A3 = 101, A4 = 100. Wir sortieren zun chst nach der letzten Komponente: 010 011 101 100 a Dadurch erhalten wir Folgendes: 0 : 010 100 1 : 011 101 Wir erhalten: 0 : 100 101 1 : 010 011 Wir erhalten: 0 : 010 011 1 : 100 101 010 100 011 101

Wir sortieren dann nach der zweitletzten Komponente: 010 100 011 101

100 101 010 011

Nun die letzte Iteration, also Sortierung nach der ersten Komponente: 010 100 011 101

010 011 100 101

Nach dem Durchlauf der for-Schleife stehen die Strings in folgender Reihenfolge in Q: r=3 r=2 r=1 010 100 010 100 101 011 011 010 100 101 011 101 nach letzter Stelle sortiert nach letzten 2 Stellen sortiert nach letzten 3 Stellen sortiert

Wir sehen also: Das Sortierverfahren arbeitet (bei diesem Beispiel) korrekt. Das motiviert folgenden Satz: Satz 1.2 (Aufwand von Bucketsort) Algorithmus 1.2 sortiert A1 , . . . , An lexikographisch korrekt in O((m + n) k) Zeit. Beweis: Wir beweisen folgende Invariante: Nach dem i-ten Durchlauf sind die Strings bez glich der u letzten i Zeichen lexikographisch aufsteigend sortiert. Daraus folgt dann insbesondere, dass beim Sortieren von k-stelligen Strings nach dem k-ten Durchlauf die Strings bez glich der letzten k Stellen (also allen Stellen) lexikographisch korrekt sortiert sind u und damit die Behauptung. Der Beweis der Invariante erfolgt durch vollst ndige Induktion uber die a Iterationsschritte, hier bezeichnet mit r.

8 r = 1: (einfaches Bucketsort nach letzter Komponente):

KAPITEL 1. BUCKETSORT

In diesem Fall folgt die Korrektheit aus Satz 1.1, da die Strings nach Satz 1.1 lexikographisch korrekt nach der letzten Stelle sortiert werden. r r + 1: Die Behauptung sei also f r r bewiesen. Betrachte nun die beiden Strings Ai und A j in der (r + 1)-ten u Iteration. Wir unterscheiden zwei F lle: a Fall I: Ai und A j werden in der (r + 1)-ten Iteration in unterschiedliche Buckets sortiert. Da Ai und A j in unterschiedliche Buckets sortiert werden, unterscheiden sich Ai und A j also an der gerade betrachteten Stelle. Die lexikographische Korrektheit der Sortierung folgt dann wieder aus Satz 1.1, da wir ja wieder einfaches Bucketsort an der (r + 1)sten Stelle von hinten betrachten. Daher sind sie lexikographisch korrekt sortiert. Fall II: Ai und A j werden in der (r + 1)-ten Iteration in das gleiche Bucket sortiert. Da die einzelnen Buckets durch Queues realisiert werden, werden die Strings in der Reihenfolge, in der sie im vorigen Durchgang schon waren, hinten eingef gt und in der n chsten Iteration bezieu a hungsweise in der Konkatenation wieder in dieser Reihenfolge ausgelesen. Da die Strings aber nach der r-ten Iteration schon lexikographisch korrekt sortiert waren, sie sich aber an der (r + 1)-ten Stelle von hinten nicht unterscheiden, sind sie dann nach den letzten (r + 1) Stellen lexikographisch korrekt sortiert. Da f r jedes Zeichen in dem String genau ein Durchlauf erfolgt, erfolgen genau k Durchl ufe. Da u a jeder dieser Durchl ufe (wie in Satz 1.1 bewiesen) in O(n + m) erfolgt, erfolgt die ganze Sortierung a daher in O (k (n + m)).

1.2.2

Sortieren von Bin rzahlen a

Als spezielle Anwendung gibt es das Sortieren von n k-stelligen Bin rzahlen in O(k n). In CoMa I a wurde aber bewiesen, dass zum Sortieren von n Zahlen ein Aufwand in der Gr enordnung O(n log n) o erforderlich ist. Der scheinbare Widerspruch ist aber keiner: Mit k Stellen kann man nur 2k paarweise verschiedene Bin rzahlen bilden. F r die Darstellung von n a u paarweise verschiedenen k-stelligen Bin rzahlen muss daher gelten: a 2k n k log n Also gilt f r dieses von n abh ngige k: u a n log n k n

1.2. SORTIEREN VON STRINGS MIT BUCKETSORT

1.2.3

Sortieren von Strings variabler L nge a

Erste Idee: Die erste Idee f r diesen Sortieralgorithmus ist es, ein Bucket hinzuzuf gen, in das die Strings sortiert u u werden, die im aktuellen Durchlauf an der betrachteten Stelle kein Zeichen haben. Weil diese Strings lexikographisch kleiner sind, steht dieses Bucket vor allen anderen Buckets. Die Sortierung erfolgt dann einfach mit Algorithmus 1.2. Beispiel 1.4 Wir betrachten die Strings bab, abc und a und wollen sie in ihre lexikographisch korrekte Reihenfolge sortieren. In der ersten Iteration erhalten wir kein Zeichen : a a: a bab abc b: bab c: abc Dann sortieren wir nach dem zweitletzten Zeichen: kein Zeichen : a a: bab a bab abc b: abc c: Und schlielich sortieren wir noch nach dem ersten Zeichen: kein Zeichen : : a a abc a abc bab b: bab c: Durch diesen Ansatz werden in jeder Iteration alle Strings betrachtet. Bezeichne max die L nge des a l ngsten dieser Strings. Dann hat dieser Sortieralgorithmus den gleichen Aufwand wie der Sortierala gorithmus 1.2 zur Sortierung von Strings der festen L nge k = max . Nach Abschnitt 1.2.1 ist also der a Gesamtaufwand dieses Algorithmus in der Klasse O ( max (n + m)). Es geht aber besser: Bezeichne total die Gesamtanzahl der Zeichen. Wir k nnen den Algorithmus so o modizieren, dass er in O( total + m) liegt. Ideen fur einen besseren Algorithmus Sei wieder
max

die L nge des Strings mit der gr ten L nge. a o a

1. Sortiere die Strings Ai nach absteigender L nge i . a 2. Verwende max -mal Bucketsort wie vorher, aber betrachte in Phase r nur die Strings Ai , f r die u i max r + 1 gilt (also die Strings, die an der aktuell betrachteten Stelle ein Zeichen haben, weil sie gen gend lang sind). u

10

KAPITEL 1. BUCKETSORT 3. Um leere Buckets zu vermeiden, bestimme vorab die n tigen Buckets in jeder Phase und kono kateniere am Ende einer Phase nur die nichtleeren Buckets. (Verringert den Aufwand zur Konkatenation auf O(#nichtleer) statt O(m).)

Algorithmus 1.3

Input: Strings (Tupel) A1 , . . . , An Ai = (ai1 , ai2 , . . . , ai i ), ai j {0, . . . , m 1}

(oder auch ein beliebiges anderes Alphabet)


max

= max
i

Output: Permutation B1 , . . . , Bn von A1 , . . . , An mit B1 lex B2 lex lex Bn Methode: 1. Generiere ein Array von Listen NONEMPTY[] der L nge max und f r jedes , 1 max eine a u Liste in NONEMPTY[ ], die angibt, welche Zeichen an einer der -ten Stellen vorkommen und welche Buckets daher in der ( total )-ten Iteration ben tigt werden. o Dazu: 1.1 Erschaffe f r jedes ai , 1 i n, 1 i ein Paar ( , ai ) (das bedeutet: das Zeichen ai u kommt an -ter Stelle in einem der Strings vor) 1.2 Sortiere die Paare lexikographisch mit Algorithmus 1.2, indem man sie als zweistellige Strings betrachtet. 1.3 Durchlaufe die sortierte Liste der ( , ai ) und generiere im Array NONEMPTY[], sortierte Listen, wobei das Array NONEMPTY[ ], 1 max eine sortierte Liste aller ai enth lt. a Dabei lassen sich auch gleich auf einfache Weise eventuell auftretende Duplikate entfernen. 2. Bestimme L nge i jedes Strings und generiere Listen LENGTH[ ] aller Strings mit L nge (nur a a Referenzen auf die Strings in LENGTH[ ] verwalten, daher nur O(1) f r Referenzen umh ngen) u a 3. Sortiere Strings analog zu Algorithmus 1.2.3, beginnend mit
max .

Aber:

nach der r-ten Phase enth lt Q nur die Strings der L nge max r + 1; diese sind lexia a kographisch korrekt sortiert bez glich der letzten r Komponenten. u
NONEMPTY [] wird benutzt, um die Listen in BUCKET[] neu zu generieren und auerdem zur schnelleren Konkatenation der Einzellisten. Dies ist n tig, weil wir nur die nichtleeren o Buckets verwalten wollen.

vor dem r + 1-ten Durchlauf wird LENGTH [ max r] am Anfang2 der Queue Q eingef gt. u Die kurzen Strings stehen dann am Anfang und damit am lexikographisch richtigen Platz, falls sie mit anderen im selben Bucket landen.
2 Das

ist zwar ein wenig ungew hnlich, bereitet aber grunds tzlich keine Probleme. o a

1.2. SORTIEREN VON STRINGS MIT BUCKETSORT

11

Wir erinnern noch einmal: BUCKET[] ist ein Array von Queues, in das sortiert wird, und Q ist eine Queue, die die Strings enth lt, die zur Zeit betrachtet werden, also gen gend lang sind. a u Wir geben nun Pseudocode f r Teil 3 von Algorithmus 1.3 an. u Algorithmus 1.4 1. Leere Q 2. for j:=0 to m 1 do 2.1 leere BUCKET[j] 3. for :=
max

downto 1 do

3.1 F ge LENGTH[ ] am Anfang von Q ein u 3.2 while Q nicht leer do 3.2.1 Sei Ai erster String in Q 3.2.2 l sche Ai in Q und f ge Ai in BUCKET[ai ] ein o u 3.3 for jedes j in NONEMPTY[ ] do 3.3.1 f ge BUCKET[j] am Ende von Q ein u 3.3.2 leere BUCKET[j] Beispiel 1.5 Sortieren wir nun die gleichen Strings wie vorher, also a, bab und abc. Weil wir mit Referenzen arbeiten, spielt die Stringl nge f r das Einf gen keine Rolle. a u u Teil 1 des Algorithmus erzeugt durch einfaches Durchlaufen der Strings folgende Paare: (1, a), (1, b), (2, a), (3, b), (1, a), (2, b), (3, c) in der Liste. Daraus liefert Algorithmus 1.2 dann die sortierte Liste (1, a), (1, a), (1, b), (2, a), (2, b), (3, b), (3, c) Durch einfaches Durchlaufen dieser sortierten Liste von links nach rechts werden daraus die Listen im Array NONEMPTY[] mit den richtigen Eintr gen gef llt: a u
NONEMPTY [1] NONEMPTY [2]

= a, b = a, b NONEMPTY [3] = b, c

Dann werden die L ngen der einzelnen Strings bestimmt: a


1

= 1,

= 3,

=3
LENGTH [],

Mit Hilfe dieser Information erzeugt der Algorithmus dann das Array eine Liste aller Strings der L nge enth lt: a a

wobei

LENGTH [

12

KAPITEL 1. BUCKETSORT

= a = 0 / LENGTH [3] = bab, abc


LENGTH [1] LENGTH [2]

Nun f hren wir den dritten Teil des Algorithmus aus, dessen Pseudocode wir angegeben haben: u Zuerst werden in Q alle Elemente von letzten Stelle sortiert:
LENGTH [ max ]

LENGTH [3]

eingef gt und dann nach der u

BUCKET[a]

= 0 / BUCKET[b] = bab BUCKET[c] = abc

Durch das Array NONEMPTY[] wissen wir, dass wir das erste Bucket gar nicht betrachten m ssen. Es u werden daher nur die letzten beiden Listen konkateniert und die Elemente am Ende von Q eingef gt. u Q enth lt nun bab,abc. Es wird daraufhin LENGTH[2] = 0 am Anfang von Q eingef gt. a / u Daraufhin wird Q nach der zweitletzten Stelle sortiert:
BUCKET[a] BUCKET[b]

= bab = abc BUCKET[c] = 0 /

Wieder wissen wir schon, dass das letzte Bucket leer ist und brauchen es daher nicht zu betrachten. Es werden die ersten beiden Listen konkateniert und am Ende von Q eingef gt. Q enth lt nun bab, abc. u a Daraufhin wird LENGTH[1] = a am Anfang von Q eingef gt, Q enth lt nun also a, bab, abc. u a Daraufhin wird Q nach der ersten Stelle sortiert: Q[a] = a, abc Q[b] = bab Q[c] = 0 / Dann werden die Listen konkateniert und wir erhalten als Ergebnis: a, abc, bab.

Zum Aufwand Um die Paare zu generieren, m ssen alle Strings durchlaufen werden und f r jedes Zeichen in jedem u u der Strings muss genau ein Paar erzeugt werden. Der Aufwand daf r ist u O( 1 +
2 + + n) = O

i=1

= O(

total )

Beim Sortieren der Paare ist

max

= 2. Dieser Teil erfordert einen Aufwand von

1.3. LITERATURHINWEISE

13

2. Komponente total Elemente

1.Komponente total Elemente

O 2

+ m +
Buckets

max total

max Buckets

O(

total

+ m)

Um NONEMPTY[] einzurichten, m ssen wir nur die sortierte Liste der Paare einmal durchlaufen, das u geht also in O( total ). Das Berechnen der L nge (O( total )) und Erzeugen des Arrays LENGTH[] (das a lmax Elemente besitzt) geht in O( total + max ) O( total ). Satz 1.3 Algorithmus 1.3 sortiert die Liste korrekt in O(
total

+ m) Zeit.

Beweis: Die Korrektheit ist klar, folgt wie in Algorithmus 1.2. Zum Aufwand: Teile 1,2 Teil 3: Sei n die Anzahl der Strings, deren L nge i gr er gleich ist. Sei m die Anzahl der verschiedenen a o Symbole, die an der Stelle auftreten. m ist dann auch gleichzeitig die L nge von NONEMPTY[ ]. a Ein Durchlauf der WHILE-Schleife 3.2 hat dann als Aufwand O(n ) (weil sich in jeder Iteration n Elemente in Q benden). Ein Durchlauf der FOR-Schleife 3.3 hat einen Aufwand von O(m ) (weil wir genau m Buckets verbinden m ssen). u Der Aufwand des Pseudocodes ist dann insgesamt: O (m + n ) .
=1
max

O( total ) + O( total + m) + Paare generieren Paare sortieren

O(

total )

O(
LENGTH

total )

NONEMPTY

einrichten

einrichten

(m
=1

max

+n )

= O O( O(

m
=1 total )

max

+n
=1 total )

max

total ) + O(

1.3

Literaturhinweise

Die Darstellung von Bucketsort folgt [HU79]. Varianten von Bucketsort (Counting Sort, Radix Sort) und eine average vase Analyse werden in [CLRS01] behandelt.

14

KAPITEL 1. BUCKETSORT

Kapitel 2

B ume und Priority Queues a


2.1 B ume a

Bisher haben wir als dynamische Datenstrukturen Listen kennengelernt. Da der Zugriff in Listen in der Regel nur sequentiell erfolgen kann, ergibt sich f r das Einf gen bzw. Suchen in einer (sortierten) u u Liste bei L nge n ein linearer Aufwand. Das heit: a

O(n) im worst case und O(n/2) im average case. Dies ist f r viele Anwendungen, in denen ein sich dynamisch andernder Datenbestand verwaltet weru den muss, zu langsam (z.B. Verwaltung von Identiern in einem Programm durch den Compiler, Autorenkatalog einer Bibliothek, Konten einer Bank, usw.). Bessere Methoden bietet unter anderem die Datenstruktur der B ume, die in diesem Kapitel erl utert wird. a a

2.1.1

Grundbegriffe

Gerichtete B ume (kurz B ume) kann man auf zwei Arten erkl ren. Eine graphentheoretische Dea a a nition 1 wurde bereits in der Coma I im Zusammenhang mit Graphen behandelt. Etwas abstrakter ist die rekursive Denition, die in der Coma I in Zusammenhang mit der Rekursion erl utert wurde. Sie a wird hier noch einmal erkl rt und in Abbildung 2.1 visualisiert: a

1 Ein

gerichteter Baum ist ein Digraph T = (V, E) mit folgenden Eigenschaften:

Es gibt genau einen Knoten r, in dem keine Kante endet (die Wurzel von T ). Zu jedem Knoten i = r gibt es genau einen Weg von der Wurzel r zu i. Dies bedeutet, dass keine zwei Wege in den gleichen Knoten einm nden. Der Graph kann sich ausgehend von der Wurzel u also nur verzweigen. Daher kommt auch der Name Baum.

15

16 Ein Baum T ist entweder leer

KAPITEL 2. BAUME UND PRIORITY QUEUES

oder er entsteht aus endlich vielen, voneinander verschiedenen B umen T1 , . . . , Tn mit Wurzeln a w1 , . . . , wn , die in T als Teilb ume unter der Wurzel w von T (einem neuen Knoten) h ngen. a a w1 wn = w r
d d d d wn w1 e . . . T e T1 e n e e e e e e e

e e T1 e Tn e ... e e e e e e

Abbildung 2.1: Baum, rekursiv aufgebaut Beispiele f r die Verwendung von B umen sind: u a Darstellung von Hierarchien Auswertung arithmetischer Ausdr cke u z.B.: ((a + b) (c + d))/e + f /g (siehe Abb. 2.6, Seite 24) Rekursionsbaum Im Zusammenhang mit B umen ist die folgenden Terminologie ublich: Bl tter, innere Knoten, Wura a zel, Kinder / S hne / Br der, Vater / Eltern, Nachfolger, Vorg nger und Teilb ume. Ein Knoten v kann o u a a einen Vater und S hne haben. Die S hne eines Vaters sind Br der. Hat ein Knoten keinen Vater, ist o o u er die Wurzel des Baumes. Hat er keine S hne, ist er ein Blatt. Wenn ein Knoten verschieden von der o Wurzel ist und mindestens einen Sohn hat, ist er ein innerer Knoten. Eine besondere Rolle spielen die bin ren B ume. Sie sind entweder leer oder bestehen aus der Wurzel a a und einem linken und einem rechten bin rem Baum (den Teilb umen). Jeder Knoten hat maximal a a zwei S hne, man spricht vom linken und vom rechten Sohn. In den folgenden Abschnitten werden o wir ausschlielich bin re B ume behandeln und deshalb das Wort Baum in der Bedeutung bin rer a a a Baum verwenden. Bekannte Beispiele bin rer B ume sind der Stammbaum mit Vater, Mutter und a a einer Person als deren Nachfolger (!) oder die Aufzeichnung eines Tennisturniers, in der jedes Spiel durch einen Knoten mit dem Namen des Gewinners charakterisiert ist und die beiden vorausgehenden Spiele als dessen Nachfolger aufgef hrt sind. u Die rekursive Struktur von B umen ist von groer Bedeutung f r viele Algorithmen auf B umen. a u a Auch viele charakteristische Gr en von B umen lassen sich rekursiv beschreiben oder denieren. o a

2.1. BAUME

17

Ein Beispiel daf r ist die H he von B umen. Die H he gibt den l ngsten Weg von der Wurzel bis zum u o a o a Blatt gemessen in Anzahl der Kanten an. Sie ergibt sich wie folgt: h(T ) = 1 falls T leer max{h(T1 ), h(T2 )} + 1 sonst (2.1)

Besteht T beispielsweise nur aus einem Knoten, ergibt sich aus Gleichung (2.1) die H he von T zu o h(T ) = max{1, 1} + 1 = 0.

2.1.2

Implementation von bin ren B umen a a

Im Folgenden wird gezeigt, wie sich bin re B ume als abstrakte Datenstruktur implementieren lassen. a a Ein Baum besteht aus Knoten und Kanten zwischen den Knoten. Die Knoten sind hier Objekte der inneren Klasse BinTreeNode. F r die Kanten nutzt man die Zeigereigenschaft von Referenzobjekten. u So kennt ein BinTreeNode das Objekt, das im Knoten steht, seinen linken und seinen rechten Sohn und in manchen Implementationen auch seinen Vater. Das wird in Abbildung 2.2 deutlich. Zus tzlich sind a get und set Methoden sinnvoll sowie Methoden, die testen, ob der linke bzw. rechte Sohn vorhanden sind. class BinTreeNode { Object BinTreeNode BinTreeNode

data; lson; rson;

// saved object // left son // right son

// sometimes also usefull BinTreeNode parent; // parent ... } // constructors, get methods, // set methods ...

Objekt
r 

Ref. auf linken Sohn

r e e e

Ref. auf rechten Sohn

Abbildung 2.2: Struktur eines Knotens Wie in Abb. 2.3 dargestellt, ist ein Baum eine Verzeigerung von Knoten. Jeder BinTreeNode zeigt auf seine S hne und, wie oben schon erw hnt, in manchen Implementationen auch auf seinen Vater. o a

18

KAPITEL 2. BAUME UND PRIORITY QUEUES

Es gibt einen BinTreeNode, hier root genannt, dessen rechter (oder linker) Sohn immer auf die eigentliche Wurzel des Baumes zeigt. Zus tzlich gibt es eine Referenz curr (lies: karr), die auf a einen beliebigen Knoten im Baum zeigt und die auf jeden Knoten umgesetzt werden kann. root
q rr

r j r

Objekt

    C 
Objekt

q s q
Objekt

% q d d d

curr


Objekt

q d d d
Objekt

q d d d

q d d d

...

... Abbildung 2.3: Baum, dargestellt als verkettete Struktur class BinTree { BinTreeNode dummy; BinTreeNode curr; ... } Das folgende Programm 2.1 stellt ein Beispiel einer abstrakten Klasse dar, von der bin re B ume a a abgeleitet werden k nnen. Einige Methoden werden im Folgenden genauer erkl rt. o a Programm 2.1 BinTree /** * abstract base class for all sorts of binary trees * * @author N.N. */ abstract class BinTree { /** * class for tree nodes */ protected class BinTreeNode {

// dummy node whose left son is the root // points at the current node

2.1. BAUME public BinTreeNode() { } // default constructor

19

public BinTreeNode(Object obj) { // init constructor } public boolean isLeaf() { } public boolean isRoot() { } public boolean isLeftChild() { } // is node a leaf in tree?

// is node root of tree?

// is node left child // of parent? // get left child

public BinTreeNode getLeftChild() { }

public BinTreeNode getRightChild() { // get right child } public BinTreeNode getParent() { } public String toString() { } } // class BinTreeNode // get parent

// conversion to string

/***

data

******************************************************/

/***

constructors

**********************************************/

// default constructor, initializes empty tree public BinTree() { } /*** get methods ***********************************************/ // is tree empty?

public boolean isEmpty() { }

20

KAPITEL 2. BAUME UND PRIORITY QUEUES // root node of tree // -> what should be returned if tree is empty?? protected BinTreeNode _getRoot() { } // current number of tree nodes public int getSize() { } // height of tree public int getHeight() { }

/***

set methods

***********************************************/

// switch debugging mode public static void setCheck(boolean mode) { }

/***

methods for current node

**********************************/

// reset current node to first node in inorder sequence public void reset() { } // does current node stand at end of inorder sequence? public boolean isAtEnd() { } // reset current node to successor in inorder sequence public void increment() { } // object referenced by current node public Object currentData() { } // ist current node a leaf? public boolean isLeaf() { }

2.1. BAUME /*** conversion methods ****************************************/

21

// convert tree to string // use getClass() somewhere so that class name of "this" shows public String toString() { }

/***

debugging methods

*****************************************/

// check consistency of links in entire tree protected boolean _checkLinks() { } } Es gibt viele Methoden, die man an oder mit B umen durchf hren kann. Dazu geh ren beispielsa u o weise Methoden zum Einf gen und L schen von Knoten, zum Durchlaufen des Baumes (vgl. Abu o schnitt 2.1.3 usw. Wir wollen uns eine m gliche Methode zum Berechnen der H he eines Baumes o o genauer anschauen. Diese benutzt die Gleichung 2.1 zur Berechnung der H he und nutzt die rekursio ve Struktur von B umen. a Programm 2.2 getHeight() int getHeight() { if (isEmpty()){ // empty tree return -1; } else { int lheight = _getRoot().getLeftSon().getHeight(); int rheight = _getRoot().getRightSon().getHeight(); return Math.max(rheight,lheight)+1; } } Implementation im Array B ume k nnen auch mit Hilfe von Arrays implementiert werden. Hierbei handelt es sich zwar nicht a o um eine dynamische Datenstruktur, diese Umsetzung ist allerdings f r manche Programmiersprachen u (z.B. FORTRAN) erforderlich. Die Idee hierbei ist, die Indizes als Zeiger auf die S hne zu nutzen. Das o l sst sich explizit (durch Abspeicherung) oder implizit (durch Berechnung) l sen. Bei der expliziten a o Variante sehen die Knoten so aus: class ArrayBinTreeNode { Object data; int lson;

22 int } rson;

KAPITEL 2. BAUME UND PRIORITY QUEUES

Der Baum wird dann, wie auch in Abbildung 2.4 veranschaulicht, als Array umgesetzt: ArrayBinTreeNode[] tree = new ArrayBinTreeNode[n];
0 1 ... i j ... n2 n1

s c
Objekt i j

... Abbildung 2.4: Baum als Array

Dazu geh ren nat rlich noch die oben schon dargestellten Zugriffsfunktionen. Die H he wird ebeno u o falls auf die schon erkl rte Weise rekursiv berechnet. a Bei der impliziten Variante werden die beiden S hne nicht im Knoten gespeichert, sondern in geto Methoden berechnet. Die Indizes der S hne des Knoten i ergeben sich bei bin ren B umen immer zu o a a 2i + 1 f r den linken Sohn und 2i + 2 f r den rechten Sohn. u u Der Nachteil an einer Implementation mit Arrays ist leider, dass man bei nicht vollen B umen im a Vergleich zur ublichen Implementation mehr Speicherplatz ben tigt. o

2.1.3

Traversierung von B umen a

Mit Traversierung eines Baumes bezeichnet man den Durchlauf von Knoten zu Knoten, um in jedem Knoten etwas zu tun. In den Knoten sind Daten, ahnlich wie in einer Liste, und um mit diesen arbeiten zu k nnen, m ssen sie nacheinander erreicht werden. Jedoch ist die Reihenfolge des Durchlaufens o u eines Baumes nicht mehr eindeutig wie bei einer Liste. Standardm ig benutzt man die folgenden a drei Traversierungen: WLR: Der Preorder-Durchlauf. Hier wird zuerst die Wurzel betrachtet, dann der linke Teilbaum mit derselben Regel und dann der rechte Teilbaum wieder mit der selben Regel. LWR: Der Inorder-Durchlauf. Hier wird zuerst der linke Teilbaum, dann die Wurzel und dann der rechte Teilbaum besucht, wobei die Teilb ume wieder mit derselben Regel durchlaufen werden. a LRW: Der Post-Durchlauf. Die Wurzel wird erst erreicht, nachdem zuerst der linke und dann der rechte Teilbaum jeweils mit derselben Regel durchlaufen wurden. Die K rzel WLR, LWR und LRW zeigen vereinfacht jeweils die Reihenfolge des Durchlaufens an. u Die Vorsilben Pre-, In- und Post- beziehen sich jeweils auf die Rolle der Wurzel.

2.1. BAUME

23

A B D E C F

Abbildung 2.5: Beispielbaum f r die Traversierung u Beispiel 2.1 Dieses Beispiel zeigt die drei Traversierungsm glichkeiten f r den Baum in Abbilo u dung 2.5. WLR: A, B, D, E, C, F LWR: D, B, E, A, C, F LRW: D, E, B, F, C, A Ist es einfach nur wichtig, unabh ngig von der Reihenfolge alle Knoten zu erreichen, spielt es keine a Rolle, welche Traversierung gew hlt wird. Allerdings gibt es verschiedene Anwendungen, die jeweils a unterschiedliche Reihenfolgen benutzen. Beim Aufrufbaum oder beim Rekursionsbaum beispielsweise, die in Coma I behandelt wurden, werden die Methoden in Postorder Reihenfolge abgearbeitet. Im folgenden Beispiel wird verdeutlicht, welchen Einuss die verschiedenen Reihenfolgen auf arithmetische Ausdr cke haben. u Beispiel 2.2 Der arithmetische Ausdruck ((a + b) (c + d))/e + f /g wird vom Compiler in einen Baum, wie in Abb. 2.6, umgewandelt. In diesem Baum stehen die Identier in den Bl ttern. In den inneren Knoten und der Wurzel stehen Operatoren. Diese verkn pfen jea u weils ihren linken Teilbaum als arithmetischen Ausdruck mit dem Ausdruck ihres rechten Teilbaums. Durchl uft man den Baum in Inorder, ergibt sich der arithmetische Ausdruck in Inx-Notation: a ((a + b) (c + d))/e + f /g Durchl uft man den Baum aber in Postorder, erh lt man den Ausdruck in Postx-Notation beziea a hungsweise umgekehrter polnischer Notation (UPN): ab + cd + e/ f g/+ Dieser wird dann vom Computer, wie in Coma I behandelt, mit Hilfe eines Stacks berechnet. Im Gegensatz zur Inx-Notation ist der Baum aus der Postx-Notation arithmetischer Ausdr cke ohu ne Hilfe von Klammern (re)konstruierbar. Indem man den Ausdruck in Postx-Notation von hinten durchl uft, kann man den Baum uber die Postorder-Reihenfolge von hinten nach vorne (wieder) aufa bauen.

24

KAPITEL 2. BAUME UND PRIORITY QUEUES

+ / + + /

b c

Abbildung 2.6: Ein arithmetischer Ausdruck als Baum dargestellt Implementation Um einen Baum in den verschiedenen Reihenfolgen zu durchlaufen, kann man sich in den JavaMethoden die rekursive Struktur der B ume n tzlich machen. Die Umsetzung zeigt die folgenden a u Methoden, die sinnvollerweise zur Klasse BinTree geh ren. o Programm 2.3 Traversierung eines Baumes void preOrderTraversal() { if (isEmpty()) { return; } // work on root getLeftSon().preOrderTraversal(); getRightSon().preOrderTraversal(); } void inOrderTraversal(){ if (isEmpty()) { return; } getLeftSon().inOrderTraversal(); // work on root getRightSon().inOrderTraversal(); } void postOrderTraversal() {

2.2. PRIORITY QUEUES if (isEmpty()) { return; } getLeftSon().postOrderTraversal(); getRightSon().postOrderTraversal(); // work on root } }

25

Neben den rekursiven Methoden gibt es auch die M glichkeit den Baum iterativ zu durchlaufen. Exo emplarisch wird hier nur die Inorder Traversierung angesprochen. Die Umsetzung wird in der Ubung behandelt. Zur iterativen Traversierung werden drei Methoden ben tigt: o 1. public void reset() 2. public void increment() 3. public boolean isAtEnd() Die Methode reset() sucht sich den am weitesten links stehenden Knoten des Baumes und setzt den curr-Zeiger auf diesen Knoten. Die Methode increment() setzt den curr-Zeiger auf den Nachfolger, also auf den n chsten Knoten entsprechend der Inorder-Reihenfolge. Die Methode isAtEnd() pr ft, a u ob der Inorder-Durchlauf das Ende erreicht hat. Objekte mit solchen Methoden bezeichnet man als Iterator und die Methoden werden dementsprechend Iteratormethoden genannt.

2.2

Priority Queues

Bei einer Priority Queue handelt es sich um eine Datenstruktur mit folgenden Kennzeichen: Sie hat einen homogenen Komponententyp, wobei jede Komponente einen Schl ssel (Wert) u besitzt. Die folgenden Operationen sind m glich: o 1. Einf gen einer Komponente u 2. Zugriff auf die Komponente mit dem kleinsten Wert 3. Entfernen der Komponente mit dem kleinsten Wert 4. Anderung des Wertes einer Komponente Die Priority Queue wurde schon in Coma I im Zusammenhang mit Heapsort behandelt. Jedoch lag dort die Aufmerksamkeit auf der Komponente mit dem gr ten Wert, nicht auf der mit dem kleinsten o Wert.

26

KAPITEL 2. BAUME UND PRIORITY QUEUES

2.2.1

M gliche Implementationen einer Priority Queue o

a) Als sortiertes Array Wenn die Anzahl n der zu speichernden Elemente bekannt ist, k nnen die Elemente in einem Array, o Abb. 2.7, gespeichert werden, wobei das kleinste Element in der ersten Komponente des Arrays steht und die ubrigen aufw rts sortiert folgen. Damit ist ein sehr schneller Zugriff auf das kleinste Element a gew hrleistet, jedoch dauern die ubrigen Operationen lange, wie in der folgenden Auistung zu sehen a ist. 1. Einf gen: u O(n) (bin re Suche + Verschieben) a 2. Zugriff: O(1) 3. Entfernen: O(n) 4. Wert andern: O(n)
0 1 2 3 4 5 6 7

12 18 24 35 44 53 63 72

kleinstes Element Abbildung 2.7: Priority Queue als sortiertes Array Eine bessere Variante ist die folgende:

b) Als Heap Wie bei Heapsort wird das Array als Baum mit Heap-Eigenschaft aufgefasst. Die Heapeigenschaft ist dann erf llt, wenn die Wege von der Wurzel zu jedem Blatt jeweils aufsteigend sortiert sind. Zur Heru stellung der Heapeigenschaft wird die Methode heapify() verwendet. Ihre genauere Funktionsweise wurde bereits in Coma I erl utert. a
0

12
r rr
2

18
4

53
6

d d
3

d d
5

35

24

63

72

44

Abbildung 2.8: Priority Queue als Heap F r die Operationen im Heap ergibt sich dann dieser Aufwand im worst case: u

2.3. LITERATURHINWEISE 1. Einf gen: u 2. Zugriff: 3. Entfernen: 4. Wert andern: O(log n) O(1) O(log n) O(log n) als Blatt in die letzte Arraykomponente einf gen u und nach oben wandern lassen letzte Komp. an die 0-te Stelle tauschen und absinken lassen aufsteigen oder absinken lassen

27

Also sind neben dem sehr schnellen Zugriff auf das kleinste Element auch die anderen Operationen schneller als im sortierten Array. Es gibt aber noch andere Implementationen, die die Operationen noch schneller, allerdings nur amortisiert, schaffen. Dazu geh ren zum Beispiel die Fibonacci Heaps. o

2.3

Literaturhinweise

B ume und Priority Queues werden in jedem Buch uber Datenstrukturen behandelt, vgl. etwa [CLRS01, Knu98, a OW02, SS02].

28

KAPITEL 2. BAUME UND PRIORITY QUEUES

Kapitel 3

Huffman Codes und Datenkompression


Das Ziel der Datenkompression ist es, Daten mit weniger Speicherplatz abzuspeichern. Abh ngig von a den Daten geschieht das verlustfrei oder nicht verlustfrei. Audio-, Video- und Bilddateien werden in der Regel komprimiert, indem Informationen weggelassen werden. Das Prinzip bei MP3-Dateien beispielsweise ist es, all die Informationen wegzulassen, die das menschliche Ohr nicht wahrnehmen kann. Somit stellt der Informationsverlust keinen Qualit tsverlust f r die gespeicherte Musik a u dar. Textdateien m chte man ohne Verlust von Informationen komprimieren. Um zu verstehen, wie o das funktioniert, muss man verstehen, wie Texte abgespeichert werden. Der folgende Abschnitt soll Aufschluss dar ber geben. u

3.1

Codierung

Wir betrachten einen Zeichensatz C (z.B. das Alphabet, ein Java Zeichensatz, alle W rter im Duden) o und ein Zeichen c C. Diese Zeichen werden im Computer mit Codew rtern codiert, und zwar uber o dem Alphabet {0, 1}. Die Gesamtheit der Codew rter f r den Zeichensatz C heit dann Code f r C. o u u Ublicherweise haben die Codew rter aller Zeichen eines Zeichensatzes C die selbe L nge. Ein solcher o a Code heit Blockcode. So sind auch der ASCII Code, bei dem alle Codew rter die L nge 8 haben, o a und der Unicode, bei dem alle Codew rter die L nge 16 haben, Blockcodes. o a Beispiel 3.1 (Blockcode der L nge 3) a Wenn C = {a, b, c, d, e, f , g, } ist, ist a b c d e f g 29 000 001 010 011 100 101 110 111

30

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

ein zugeh riger Blockcode der L nge 3. o a Es gibt auch Codes, bei denen die L nge der Codew rter der einzelnen Zeichen eines Zeichensatzes a o C unterschiedlich lang ist, die sogenannten variable length codes. Beispiel 3.2 ( variable length code) Wir betrachten wieder C = {a, b, c, d, e, f , g, }. a b c d e f g 0 1 10 11 100 101 110 111

Eine Textdatei ist nun eine Folge von Zeichen c C. Um sie abzuspeichern, muss sie verschl sselt u werden. Die Verschl sselung oder auch Codierung entspricht dem Ersetzen jedes Zeichens durch u sein Codewort. Damit die Datei sp ter wieder lesbar ist, m ssen die Codew rter wieder in die Zeia u o chen des Zeichensatzes umgewandelt werden. Die Entschl sselung bzw. Decodierung entspricht dem u umgekehrten Prozess. Das Codieren/Decodieren einer Nachricht entspricht also einer bijektiven Abbildung. Beispiel 3.3 (Codierung/Decodierung mit Blockcode) Angenommen, die Datei besteht aus diesen Zeichen:

fa gaga gaff fege Wird die Datei mit der Codetabelle von Beispiel 3.1 codiert, ergibt sich diese Bitfolge:

101 000 111 110 000 110 000 111 110 000 101 101 111 101 100 110 100 Die Decodierung ist hier sehr einfach, da wir wissen, dass drei Bits immer einem Zeichen entsprechen. Es entsteht wieder eindeutig unsere Datei:

101 000 111 110 000 110 000 111 110 000 101 101 111 101 100 110 100
f a g a g a g a f f f e g e

3.1. CODIERUNG Beispiel 3.4 (Codierung / Decodierung mit variable length code) Betrachten wir jetzt diese beiden Dateien:

31

Datei 1: abba Datei 2: ag Mit der Codetabelle von Beispiel 3.2 codiert, sehen sie so aus: (abba) 0110 (a g ) Datei 2: 0110

Datei 1:

Doch mit der Decodierung wird es schwer, denn die Dateien sind nicht mehr eindeutig entschl sselbar. u Man sagt, der Code von Beispiel 3.2 ist nicht eindeutig entzifferbar. Ein Code heit also eindeutig entzifferbar, wenn verschiedene Dateien, codiert mit dem selben Code, auch zu verschiedenen Codierungen f hren. Der Grund daf r, dass der Code von Beispiel 3.2 u u nicht eindeutig entzifferbar ist, liegt in der Beschaffenheit der Codew rter. Das Problem besteht daro in, dass es Codew rter gibt, die auch durch Zusammensetzen anderer Codew rter entstehen k nnen. o o o So ist zum Beispiel das Codewort von g, die 110, identisch mit den hintereinander geschriebenen Codew rtern von d und a, die auch 110 ergeben. Es gibt keine M glichkeit zu unterscheiden, ob dort ein o o g oder ein d und ein a steht. Eine L sung f r dieses Problem sind pr xfreie Codes. o u a

3.1.1

Pr xcode a

Ein Code heit Pr xcode1 , wenn kein Codewort Anfangsst ck eines anderen Codewortes ist. Jeder a u Blockcode ist zum Beispiel ein Pr xcode, weil kein Codewort in einem anderen enthalten sein kann. a Aber auch variable length codes k nnen pr xfrei sein. o a Lemma 3.1 Jeder Pr xcode ist eindeutig entzifferbar. a Beweis: Beim Lesen der codierten Datei ist eindeutig klar, wann ein Codewort zu Ende ist. Dann l sst a sich eindeutig sagen, welches Zeichen mit diesem Codewort codiert wurde.

Die Umkehrrichtung von Lemma 3.1 gilt aber nicht. Nicht jeder eindeutig entzifferbare Code muss ein Pr xcode sein. Das zeigt das folgende Beispiel: a
1 Der Name ist etwas verwirrend, denn eigentlich m sste der Code pr xfreier Code heien. Aber Pr xcode hat sich in u a a der Literatur durchgesetzt.

32

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Beispiel 3.5 Wir betrachten diesen Code: a b c 1 100000 00

Auch wenn dieser Code nicht pr xfrei ist, kann man codierte Dateien wieder decodieren, indem man a die Nullen z hlt. Steht hinter einer Eins eine gerade Anzahl von Nullen, handelt es sich um ein a mit a entsprechend vielen cs dahinter. Steht aber hinter einer Eins eine ungerade Anzahl von Nullen, und zwar mindestens f nf, handelt es sich um ein b mit entsprechend vielen cs dahinter. Daf r ist es aber u u unter Umst nden n tig, sich erst die ganze Datei anzusehen, um zu wissen wie viele Nullen nach den a o Einsen kommen. Es ist also m glich, den folgenden codierten Text zu entschl sseln: o u 1
a

00 00
c c

1
a

00 100000
c b

Im weiteren Verlauf werden wir uns nur noch mit Pr xcodes befassen, da vor allem diese in der a Praxis ublich sind. Lemma 3.2 Pr xcodes lassen sich mit bin ren B umen T identizieren, bei denen die Zeichen c C a a a in den Bl ttern stehen und die Wege von der Wurzel bis zum Blatt die Codew rter bilden (eine Kanten a o nach links entspricht der 0, eine Kante nach rechts entspricht der 1). Beweis: =: Sei C ein Zeichensatz mit einem zugeh rigen Pr xcode. Konstruiere einen Baum T , in dem o a pro Codewort der Weg gegangen wird, der durch die 0 bzw. die 1 vorgegeben ist. Bei der 0 gehe nach links, bei der 1 nach rechts. Da der Code pr xfrei ist, endet man immer in einem Blatt. a Es ergibt sich also ein Baum mit den geforderten Eigenschaften. =: Sei C ein Zeichensatz und T ein Baum mit den Zeichen c C in seinen Bl ttern. Betrachte a den Weg von der Wurzel zu den Zeichen c als Codewort f r jedes einzelne Zeichen, wobei u der Weg nach links der 0 und der Weg nach rechts der 1 entspricht. Da die Zeichen in den Bl ttern des Baumes stehen, ist klar, dass kein Weg zu einem Zeichen in einem Weg zu einem a anderen Zeichen enthalten sein kann. Daher kann kein Codewort Anfangsst ck eines anderen u Codewortes sein. Also handelt es sich bei dem Code um einen Pr xcode. a

Beispiel 3.6 Der Baum T in Abb. 3.1 entspricht diesem Pr xcode: a a b c d e 00 01 100 11 101

3.2. DER HUFFMAN ALGORITHMUS


0 0 1 1 0 1

33

b c

Abbildung 3.1: Pr xcode als Baum a Kommen wir nun zur ck zur Frage der Komprimierung. Der ben tigte Speicherplatz f r eine Textdatei u o u entspricht immer der Anzahl der Bits bez glich ihrer Codierung. u Betrachten wir noch einmal Beispiel 3.3 fa gaga gaff fege und codieren es mit dem Code von Beispiel 3.1,
f a g a g a g a f f f e g e

101 000 111 110 000 110 000 111 110 000 101 101 111 101 100 110 100 so ben tigen wir 17 3 = 51 Bits. Codiert man aber das Beispiel mit dem Code von Beispiel 3.2, o
f a g a g a g a f f f e g e

101 0 111 110 0 110 0 111 110 0 101 101 111 101 100 110 100 ben tigt man 43 Bits. o Verschiedene Codierungen nehmen also unterschiedlich viel Speicherplatz in Anspruch. Bei der Komprimierung wird also (dateiabh ngig) ein Code gefunden, der den Speicherplatz reduziert. Dieser Coa de muss nat rlich ein Pr xcode sein, damit die Datei wieder einfach decodierbar ist. u a

3.2

Der Huffman Algorithmus

Textdateien werden standardm ig im Blockcode codiert und gespeichert. Der Huffman Algorithmus a konstruiert einen Pr xcode variabler L nge, so dass die Anzahl der ben tigten Bits kleiner wird. a a o Der Code wird so konstruiert, dass Zeichen, die sehr h ug auftreten, kurze Codew rter bekommen, a o und weniger h uge Zeichen l ngere Codew rter. So wird, abh ngig von der Datei, der ben tigte a a o a o Speicherplatz verringert. Der Huffman Algorithmus ist sogar so gut, das der entstehende Pr xcode a optimal bez glich des ben tigten Speicherplatzes ist. Es sind Speicherplatzeinsparungen von 20% bis u o 90% ublich, je nach Beschaffenheit der Datei.

34

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Um den optimalen Pr xcode zu konstruieren, muss die Datei erst einmal gelesen werden, wobei die a H ugkeiten f (c) f r alle Zeichen c C ermittelt werden. Ist die H ugkeit der Zeichen bekannt, a u a und wird die Datei mit dem Pr xcode T (als bin rer Baum aufgefasst) codiert, so ergibt sich der a a ben tigte Speicherplatz der Dateiwie folgt: o B(T ) =

cC

f (c) hT (c)

(3.1)

Dabei gibt hT (c) die H he des Zeichens c im Baum T an, also die Anzahl der Kanten des Baumes o von der Wurzel bis zu dem Blatt, in der das Zeichen c steht, an. Dies entspricht nach Lemma 3.1 der L nge des Codewortes f r das Zeichen c. a u Beispiel 3.7 zeigt, wie der Speicherplatz bei unterschiedlichen Codierungen variieren kann. Zeichen c a b c d e f f (c) in 1000 45 13 12 16 9 5 Code 1 000 001 010 011 100 101 Code 2 0 101 100 111 1101 1100

Code 1
0 0 0 1 1 0 1 0 1 0 1 0

Code 2
1 0 0 1 1 0 1

b c

b
0 1

d e

f
Abbildung 3.2: Die B ume der beiden Codes a Dann ergibt sich der ben tigte Speicherplatz f r Code 1 zu: o u B(T1 ) = (45 + 13 + 12 + 16 + 9 + 5) 1000 3 = 300000 Der ben tigte Speicherplatz f r Code 2 betr gt hingegen: o u a B(T2 ) = (45 1 + 13 3 + 12 3 + 16 3 + 9 4 + 5 4) 1000 = 224000

3.2. DER HUFFMAN ALGORITHMUS

35

Wir wollen wir uns nun Huffman Algorithmus ansehen, der f r jede Textdatei einen optimalen Pr xcode u a ermittelt. Algorithmus 3.1 (Huffman Algorithmus) 1. Fasse jedes Zeichen c C als einelementigen Baum auf und f ge es in eine Priority Queue Q u ein, wobei die H ugkeit f (c) als Schl sselwert dient. a u 2. Solange Q mehr als einen Baum enth lt: a W hle die beiden B ume T1 und T2 mit den kleinsten H ugkeiten (muss nicht eindeutig a a a sein). Entferne sie aus Q. Konstruiere einen neuen Baum aus den T1 , T2 als Teilb ume unter einer neuen Wurzel und a gebe ihm die H ugkeit f (T1 ) + f (T2 ). a F ge diesen Baum in Q ein. u 3. Gebe (den einzig ubrig gebliebenen Baum) T in Q zur ck. Dieser Baum (der so genannte Huffu man Baum oder Huffman Code) ist ein optimaler Pr xcode. a Bei der Codierung einer Datei gem T muss neben der codierten Datei nat rlich der Code z.B. als a u Baum mit abgespeichert werden, denn er ist zur Decodierung notwendig. Der Speicherplatz daf r ist u aber bei gen gend groen Dateien im Vergleich zum eingesparten Speicherplatz so gering, dass er u vernachl ssigt werden kann. a Das folgende Beispiel zeigt, wie der Huffman Algorithmus funktioniert: Beispiel 3.8 (Konstruktion eines Huffman Baumes)

Zeichen c f (c)

a 45

b 13

c 12

d 16

e 9

f 5

Die Zeichen werden alle als einknotige B ume mit f (c) als Schl ssel in die Priority Queue Q eina u gef gt: u

45

13

12

16

Q:

Die beiden B ume mit den kleinsten Schl sseln werden aus Q entfernt, zu einem neuen Baum zusama u mengef gt und wieder in Q eingef gt: u u

36
45

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION


13 12 16 14

Q:

Das wird fortgesetzt, bis nur noch ein Baum in Q ist:

45

25

16

14

Q:

45

25

30

Q:

45

55

Q:

3.2. DER HUFFMAN ALGORITHMUS


45

37

Q:
a

e
Am Ende wird der fertige Huffman Baum von Q entfernt:

45

Die Laufzeit des Huffman Algorithmus


Ist die Priority Queue als Heap implementiert (siehe Abschnitt 2.2.1 auf Seite 26) und hat man n Zeichen, so ergibt sich folgende Laufzeit f r den Huffman Algorithmus: u 1. 2. alle Zeichen einf gen in Q: u n 1 Phasen: - die beiden Kleinsten aus Q entfernen: - neuen Baum bauen: - wieder einf gen in Q: u 3. Baum zur ck geben: u insgesamt: O(3n) n 1 mal: O(2 log n) O(1) O(log n) O(1) O(n log n)

38

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Die Optimalit t des Huffman Codes a


Ein Pr xcode T heit optimal f r einen Zeichensatz C und H ugkeiten f (c), c C, wenn a u a B(T ) B(T ), f r jeden anderen Pr xcode T (zu C und denselben H ugkeiten f (c)). u a a Lemma 3.3 Sei C eine Menge von Zeichen mit den H ugkeiten f (c). Seien x, y die Zeichen mit den a niedrigsten H ugkeiten. Dann gibt es einen optimalen Pr xcode T , in dem x und y die gr te H he a a o o und gemeinsamen Vater haben. Die beiden Codew rter f r x und y haben dann dieselbe L nge und o u a unterscheiden sich nur im letzten Bit. Beweis: Die Idee des Beweises ist es, einen Baum T zu betrachten, der einen optimalen Pr xcode repr sentiert a a und ihn gegebenenfalls so zu modizieren, dass er optimal bleibt und die beiden Zeichen x und y in den Bl ttern mit der gr ten H he stehen und denselben Vater haben. Ist das m glich, sind die beiden a o o o gew nschten Eigenschaften im optimalen Pr xcode erf llt. Abbildung 3.3 skizziert diese Vorgehensu a u weise. T s rr rs s d x s ds d y s ds a b T s rr rs s d a s ds d y s ds x b
E

(3.2)

T s rr rs s d a s ds d b s ds x y

Abbildung 3.3: Modizieren des Baumes T f r den Beweis von Lemma 3.3 u Zun chst uberlegen wir uns, dass es einen optimalen Pr xcode gibt. Dies folgt daraus, dass der Wert a a B(T ) immer ganzzahlig und positiv ist. In dieser Menge von Zahlen existiert ein kleinster Wert B(T ), und der zugeh rige Baum T ist ein optimaler Pr xcode. o a Sei also nun T ein optimaler Pr xcode. Sei a ein Blatt in T mit gr ter H he hT (a). Dann hat a a o o aufgrund der Optimalit t von T einen Bruder b, denn h tte a keinen Bruder, k nnte man a einen a a o Level h her h ngen und h tte den Wert B(T ) verbessert, was im Widerspruch zur Optimalit t von o a a a T st nde. Betrachte nun x und y, die beiden Zeichen mit den geringsten H ugkeiten. Vertauscht man u a a und x im Baum T , so entsteht der Baum T . F r den Speicherplatz der beiden B ume gilt dann: u a B(T ) B(T ) = =
cC

f (c) hT (c) f (c) hT (c)


cC

f (x) hT (x) + f (a) hT (a) f (x) hT (x) f (a) hT (a)


=hT (a) =hT (x)

= ( f (a) f (x)) (hT (a) hT (x))


0 0

0 = B(T ) B(T )

3.2. DER HUFFMAN ALGORITHMUS

39

Da T aber optimal ist, kann es keinen Pr xcode geben, der weniger Speicherplatz ben tigt. Also gilt: a o B(T ) = B(T ) Der Pr xcode T ist also auch optimal. a Entsteht T , indem man in T b und y vertauscht, l sst sich auf analoge Weise zeigen, dass auch T a optimal ist. T erf llt dann die Aussagen des Lemmas. u

Lemma 3.4 (Prinzip der optimalen Substruktur) Sei C ein Zeichensatz mit den Zeichen c C und den H ugkeiten f (c), und seien x und y die beiden Zeichen mit den geringsten H ugkeiten. Sei T a a ein Pr xcode f r C und f (c), in dem x und y einen gemeinsamen Vater z haben. Sei T der Baum, a u der aus T entsteht, indem x und y wegfallen, statt dessen aber z als neues Zeichen mit der H ugkeit a f (z) = f (x) + f (y) hinzukommt. T ist dann ein Pr xcode f r C := C \ {x, y} {z}. a u Unter diesen Voraussetzungen gilt: T ist optimal f r C u T ist optimal f r C u

Beweis: Da wir nur die R ckrichtung ben tigen, wollen wir nur zeigen: u o T ist optimal f r C u F r T und T gilt: u B(T ) B(T ) = f (x)hT (x) + f (y)hT (y) f (z) hT (z)
=:

T ist optimal f r C u

(hT (x) = hT (y) = + 1, da x und y S hne von z) o = f (x)( + 1) + f (y)( + 1) ( f (x) + f (y)) = ( f (x) + f (y))( + 1) ( f (x) + f (y)) = ( f (x) + f (y))( + 1 ) = B(T ) B(T ) = f (x) + f (y) (3.3) = B(T ) = B(T ) + f (x) + f (y)

Sei T optimal, T aber nicht. Betrachte den optimalen Baum T f r C, d.h. B(T ) < B(T ). Nach u Lemma 3.3, darf angenommen werden, dass x und y an der tiefsten Stelle im Baum T stehen und einen gemeinsamen Vater w haben. Betrachte nun den Baum T , der entsteht, wenn x und y im Baum T wegfallen und w als neues Zeichen mit der H ugkeit f (w) = f (x) + f (y) hinzukommt. Dann a ergibt sich nach Gleichung 3.3 f r den Speicherbedarf: u B(T ) = B(T ) + f (x) + f (y)

40

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Da T optimal f r C ist und T ein Pr xcode f r C und dieselben H ugkeiten ist, folgt B(T ) u a u a B(T ). Damit gilt: B(T ) < B(T ) = B(T ) + f (x) + f (y) B(T ) + f (x) + f (y) = B(T ) Das ergibt einen Widerspruch. Also muss auch T optimal sein.
3.3

Satz 3.1 (Optimalit t) Der Huffman Code T ist optimal unter allen Pr xcodes, das heit: a a B(T ) := f r alle Pr xcodes T . u a Beweis: (Induktion nach der Anzahl der Zeichen n = |C|) Induktionsanfang: F r n = 2 liefert der Algorithmus eine Codierung, bei denen die Codew rter nur u o aus einer 0 bzw. 1 bestehen. Das entspricht dem optimalen Speicherplatz. Induktionsschritt von n 1 auf n: Sei n = |C|. Der Huffman Algorithmus ermittelt die Zeichen x und y mit den kleinsten H ugkeiten und ersetzt sie durch einen neuen Baum, mit dem Zeichen z a in der Wurzel und den beiden S hnen x und y, wobei f (z) = f (x) + f (y) ist. Danach wird mit dem o Zeichensatz C = C\{x, y} {z} weitergearbeitet. Nach Induktionsvoraussetzung liefert der Huffman Algorithmus einen optimalen Baum T f r C . Ersetzt man z wieder entsprechend Lemma 3.4, so u erh lt man einen optimalen Pr xcode T f r C. Da der Huffman Algorithmus gerade auf diese Weise a a u den Baum T konstruiert, ist der Huffman Code optimal unter allen Pr xcodes. a

cC

f (c) hT (c) B(T

Bemerkungen zu Huffman Codes


Hier soll nochmal auf besondere Eigenschaften des Huffman Algorithmus und auf Alternativen dazu hingewiesen werden. Der Huffman Algorithmus entspricht einer zeichenweisen Codierung. Es wird jedem Zeichen c C ein eigenes Codewort zugewiesen. Wie wir sp ter noch sehen werden, gibt es auch Algorithmen, die a Codew rter f r Teilstrings konstruieren. Auch beim Huffman Algorithmus w re das m glich, indem o u a o man Strings der L nge k als Zeichen betrachtet. a Beim Huffman Code handelt es sich um einen statischen Code. Das bedeutet, dass die ganze Nachricht vorab gelesen und analysiert wird, um die H ugkeiten der einzelnen Zeichen zu ermitteln und a

3.3. WEITERE DATENKOMPRESSIONSVERFAHREN

41

dementsprechend feste Codew rter zu konstruieren. Danach muss die Datei noch einmal gelesen wero den, um sie mit den entstandenen Codew rtern zu codieren. Das Gegenteil hierzu w ren die dynamio a schen bzw. adaptiven Codes. Bei diesen Codierungen werden die Codew rter w hrend des Lesens des o a Textles erstellt und im Laufe des Lesens ge ndert, wenn es mehr Informationen uber die Nachricht a gibt. Die Datei wird w hrend des Lesens codiert, und zwar mit sich andernden Codew rtern. Diese a o Vorgehensweise erspart ein zweimaliges Lesen. Das dynamische Codieren wird auch Komprimierung on the y genannt. Die Datenkompression mittels des Huffman Algorithmus ist im Gegensatz zur Kompression von Audio-, Video- und Graphikdateien verlustfrei. Die urspr ngliche Nachricht kann also ohne Verlust u von Informationen wieder rekonstruiert werden.

3.3
3.3.1

Weitere Datenkompressionsverfahren
Der adaptive Huffmancode

Im Gegensatz zum statischen Huffmancode, wird bei diesem Verfahren ein dynamischer Code erstellt. Im Laufe des Lesens werden zu jedem Zeitpunkt, abh ngig von der schon gelesenen Nacha richt, die wahrscheinlichen H ugkeiten abgesch tzt und auf dieser Grundlage die Codew rter era a o stellt. Der Pr xcode wird also immer so ver ndert, dass er f r die aktuellen Absch tzungen optimal a a u a ist. Beim Verschl sseln wird die Beschaffenheit der Quelldatei gelernt. Beim Entschl sseln muss u u der Huffman Baum kontinuierlich aktualisiert werden, damit die Zeichen wieder mit den richtigen Codew rtern ubersetzt werden k nnen. Wie oben schon beschrieben liegt der Vorteil darin, dass die o o Quelldatei nur einmal gelesen werden muss. Abh ngig von der Datei, kann diese Vorgehensweise a bessere, aber auch schlechtere Leistung bringen. Der Algorithmus bildet die Basis f r den Unixbefehl u compact, der in der Regel eine Kompressionsrate von 30-40% erbringt.

3.3.2

Der run length code

Dieses Verfahren wird zum Komprimieren von Bildern verwendet. Der Computer speichert Bilder, indem er sie in viele Bildpunkte (Pixel) aufteilt und sich die genaue Farbe eines Pixels merkt. Die Pixel werden dann in einer bestimmten Reihenfolge (z.B. zeilenweise) abgespeichert. Um das Bild nun zu komprimieren, werden nicht alle Pixel gespeichert, sondern es wird ausgenutzt, dass oft Wiederholung eintritt (z.B. schwarze Fl che). Daher werden nur Pixel mit der Vielfachheit ihres wiederholten a Auftretens gespeichert. Damit wird Speicherplatz eingespart.

3.3.3

Der Lempel-Ziv Code

Dieser Algorithmus wurde 1977 entwickelt. Er arbeitet verlustfrei und adaptiv. Es ist leider nicht m glich f r ihn eine Optimalit tsaussage zu treffen, jedoch ist er empirisch gut. Typisch sind Leiso u a tungen, die in der Gr enordnung von 50 60% liegen. Da er in zip, compress und gzip genutzt wird, o soll er hier genauer erkl rt werden. a

42

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Der Lempel-Ziv Algorithmus erstellt sog. Ketten, die Strings wachsender L nge entsprechen. In a jedem Schritt des Algorithmus wird von der Rest-Nachricht, die noch nicht codiert wurde, der l ngste a Pr xcode ermittelt, der einer bereits denierten Kette entspricht. Diese wird dann mit dem danach a kommenden Zeichen c als String c in eine Tabelle, dem sog. W rterbuch, eingetragen und sie wird o mit ic codiert, wobei i dem Codewort von entspricht. Die Kette ic erh lt dann ein eigenes Codewort. a Die Codew rter haben dieselbe vordenierte L nge, die dann die Gr e der Tabelle und die L nge o a o a der l ngsten Kette bestimmt. a Um den Lempel-Ziv Algorithmus besser zu verstehen, folgen hier zur Veranschaulichung zwei Beispiele. Beispiel 3.9 Gegeben sei die Nachricht: aa bbb cccc ddddd eeeeee fffffffgggggggg und der dazugeh rige Blockcode: o Zeichen a b c d e f g Codewort 000 001 010 011 100 101 110 111

Daraus ergibt sich dann mit dem beschriebenen Verfahren der Lempel-Ziv Code: String Kette Codewortnummer String Kette Codewortnummer leer 0 0 eee 13e 14 a 0a 1 f 5f 15 a 1 2 f 0f 16 b 0b 3 ff 16f 17 bb 3b 4 fff 17f 18 0 5 g 0g 19 c 0c 6 cc 6c 7 c 6 8 ggg 20g 21 d 0d 9 dd 9d 10 dd 10 11 e 0e 12 ee 12e 13

gg 19g 20

Die komprimierte Nachricht sieht dann so aus: (0a)(1 )(0b)(3b)(0 )(0c)(6c)(6 )(0d)(9d)(10 )(0e)(12e)(13e)(5f)(0f)(16f)(17f)(0g)(19g)(20g)(20) Um 21 Codewortnummern abzuspeichern, ben tigt man log 21 = 5 Bit. F r die Zeichen an sich o u werden zum Abspeichern die urspr nglichen 3 Bit ben tigt. Dann folgt f r den Speicherplatz: u o u 21 Zeichen + 1 Zeichen a a 5 Bit 5 Bit + 3 Bit = = 168 Bit 5 Bit 173 Bit

3.4. ABSCHLIESSENDE BEMERKUNGEN

43

Beispiel 3.10 Das nun folgende Beispiel benutzt den uns bereits bekannten ASCII Code, der eine L nge von 8 Bit hat: a schers fritze scht frische sche frische sche scht schers fritze Der Lempel-Ziv Code sieht dann wie folgt aus String Kette Codewortnummer String Kette Codewortnummer String Kette Codewortnummer leer 0 0 sc 3c 14 isch 23h 27 f 0f 1 ht 5t 15 t 0t 28 i 0i 2 0 16 26i 29 s 0s 3 fri 9i 17 c 0c 4 sch 14h 18 h 0h 5 e f 12f 19 s f 8f 31 e 0e 6 is 2s 20 ri 7i 32 r 0r 7 s 3 8 ch 4h 21 tz 28z 33 fr 1r 9 e fr 19r 22 it 2t 10 isc 20c 23 z 0z 11 e 19i 24 e 6 12 1i 13 f 16f 26

sche 18e 25

scher 25r 30

und codiert die Nachricht folgendermaen: (0f)(0i)(0s)(0c)(0h)(0e)(0r)(3 )(1r)(2t)(0z)(6 )(1i)(3c)(5t)(0 )(9i)(14h)(12f) (2s)(4h)(19r)(20c)(19i)(18e)(16f)(23h)(0t)(26i)(25r)(8f)(7i)(28z)(6) Zum Abspeichern von 33 Codew rtern werden log 33 = 6 Bit und zum Abspeichern eines Zeichens o mit ASCII Code werden 8 Bit ben tigt. Das heit f r den Speicherplatzbedarf: o u 33 (6Bit + 8Bit) + 6Bit = 468Bit

3.4

Abschlieende Bemerkungen

Abschlieend soll darauf hingewiesen werden, dass es eine von den H ugkeiten abh ngige untere a a Schranke f r Datenkompression, die Entropie, gibt. Um diese zu erkl ren ben tigen wir die folgenden u a o beiden Begriffe. Zum Einen gibt es den Begriff der normierten H ugikeit P(c), die die H ugkeit eia a nes Zeichens c in Abh ngigkeit von der Summe der H ugkeiten aller Zeichen der Quelldatei angibt: a a P(c) = f (c) f (u) (3.4)

uC

Wird der Speicherplatz B(T ), der die Gesamtheit der Wortl ngen angibt, normiert, ergibt sich die a mittlere Wortl nge: a A(T ) = P(c) h(c) (3.5)
cC

Nun k nnen wir die Entropie H(C) einer Quelldatei C denieren: o H(C) =
cC

[P(c) ( log P(c))]

(3.6)

44

KAPITEL 3. HUFFMAN CODES UND DATENKOMPRESSION

Der Satz von Shannon sagt nun, dass die mittlere Wortl nge jeder verlustfreien Komprimierung uber a der Entropie liegt: A(T ) H(C) f r jede Codierung T von C u (3.7) Um nun quantitativ sagen zu k nnen wie gut ein Kompressionsverfahren ist, gibt es den Begriff der o Redundanz . Die Redundanz kann als Differenz zwischen der mittleren Wortl nge der codierten Datei a und der Entropie der Quelldatei deniert werden: R(T ) = A(T ) H(C) f r eine Codierung T von C u (3.8)

Beispiel 3.11 In der gegebenen Quelldatei treten die folgenden Zeichen mit den angegebenen normierten H ugkeiten auf: a cC P(c) a 0, 45 b 0, 13 c 0, 12 d 0, 16 e 0, 09 f 0, 05

a Dann folgt mit Gleichung 3.6, dass die Entropie H(c) = 2, 2199 betr gt. Komprimiert man die Datei mit dem Huffman Code, ergibt sich mit Gleichung 3.5 eine mittlere Wortl nge von A(T ) = 2, 24. Die a Redundanz betr gt dann nach Gleichung 3.8 R(T ) = 0.0201. Die Redundanz ist also beim Huffman a Code sehr gering. Der Huffman Code ist asymptotisch optimal unter allen Codierungsverfahren. Betrachtet man n mlich a den verallgemeinerten Huffman Block Code, der Teilstrings fester L nge k als einzelne Zeichen bea handelt, gilt folgender Satz: Satz 3.2 Zu jedem > 0 gibt es ein k, so dass f r den Huffman Block Code Tk mit den Teilstrings der u L nge k gilt: a A(Tk ) H(C) +

3.5

Literaturhinweise

Der Huffman Algorithmus wird ausf hrlich [CLRS01] behandelt. Eine ausgezeichnete Ubersicht und ach tieferu gehende Informationen uber Kompressionsverfahren ndet man unter http://www.data-compression.com/

Kapitel 4

Suchb ume a
Die Hintergrundanwendung f r Suchb ume ist das Verwalten von dynamischen Daten. Wir m chten u a o die Operationen Einf gen u L schen o Suchen schnell ausf hren. Suchb ume haben viele Anwendungen, zum Beispiel in Datenbanken oder Dateiu a systemen auf Festplatten. Wir kennen daf r bisher nur Listen; der Hauptnachteil an Listen ist der rein u sequentielle Zugriff, der zu einem Worst Case Aufwand von O(n) f r das Suchen f hrt. Wir beschleuu u nigen die Suche durch die Verwendung von Suchb umen und erhalten dabei O(log n) statt O(n) als a Aufwand. Was ist also ein Suchbaum? Ein Suchbaum hat in jedem Knoten einen Datensatz und die Suchschl ssel sind aufsteigend sortiert bez glich der Inorder-Traversierung. u u
7

10

45

46 Aquivalent dazu ist folgende Denition: F r jeden Knoten v gilt: u

KAPITEL 4. SUCHBAUME

1. Alle Knoten im linken Teilbaum zu v haben einen kleineren Schl ssel als v u 2. Alle Knoten im rechten Teilbaum zu v haben einen gr eren Schl ssel als v o u

4.1
4.1.1

Basisoperationen in Suchb umen a


Suchen nach Schlussel k

1. Beginne in der Wurzel w: falls der Schl ssel in w den Wert k hat, gebe w zur ck u u 2. sonst falls der Schl ssel in w > k: suche im linken Teilbaum weiter u 3. sonst suche im rechten Teilbaum weiter Der Aufwand, gemessen in der Anzahl der Vergleiche, entspricht der H he des zu suchenden Knoten o plus eins. Der Worst-Case-Aufwand ist daher h(T ) + 1 = O(h(T )).

4.1.2

Einfugen eines Knoten

Das nat rlichen Einf gen funktioniert folgendermaen: u u 1. Nach dem neuen Schl ssel suchen, bis man in einem Blatt angelangt ist u 2. Dann gem Schl sselwert des Blattes den neuen Schl ssel links oder rechts an das Blatt a u u anh ngen a Als Beispiel f gen wir die Sequenz 5,7,8,3,2,12,0,6,9 in einen Suchbaum ein und stellen einige Teilu schritte in Abbildung 4.1 dar. Der Aufwand zum Einf gen in den Suchbaum T entspricht der H he des Blattes, an das angeh ngt u o a wird, plus eins. Der Worst Case hat also den Aufwand h(T ) + 1 = O(h(T )). Ein Problem beim nat rlichen Einf gen besteht darin, dass der Baum zu einer Liste entarten kann und u u Suchen und Einf gen dann einen Worst-Case von O(n) haben, siehe Abblidung 4.2. u

4.1.3

L schen eines Knoten o

1. Suche den zu l schenden Knoten v. o 2. Falls v Blatt ist, so l sche v. o 3. Falls v nur einen Sohn w hat, so h nge w an den Vater von v und l sche v. a o

4.1. BASISOPERATIONEN IN SUCHBAUMEN

47

5 7 2 0 3

5 7 6 8 12 9

Abbildung 4.1: Nat rliches Einf gen der Sequenz 5,7,8,3,2,12,0,6,9 in einen Suchbaum. u u

1 2 3 4

Abbildung 4.2: Durch nat rliches Einf gen zu einer Liste entarteter Suchbaum. u u 4. Falls v zwei S hne hat: o 4.1 Suche den Knoten w im linken Teilbaum von v, der am weitesten rechts steht (dieser ist Vorg nger von v bzgl. Inorder). a 4.2 Tausche die Daten von v und w. 4.3 L sche w (w ist Blatt oder hat nur einen Sohn und kann daher mit Schritt 1 oder 2 gel scht o o werden). Statt den am weitesten rechts stehenden Knoten im linken Teilbaum zu suchen, kann man nat rlich u auch den am weitesten links stehenden Knoten im rechten Teilbaum suchen und analog verfahren. Beispiel 4.1 Es soll die 7 aus dem Suchbaum links in Abbildung 4.3 gel scht werden. Zuerst wird o der am weitesten rechts stehende Knoten im linken Teilbaum der 7 gesucht und liefert die 6 (Mitte). Daraufhin werden die 6 und die 7 vertauscht und die 7 gel scht (rechts). o Wie beim Suchen und Einf gen betr gt der Aufwand im Worst Case h(T ) + 1 = O(h(T )). u a Satz 4.1 Der Aufwand f r das Suchen, das nat rliche L schen und das nat rliche Einf gen erfordert u u o u u im Worst Case O(h(T )) Vergleiche.

48
7 5 4 2 6 8 9 10 12

KAPITEL 4. SUCHBAUME

7 5 4 2 1 3 6 8 9 10 12 2 1 3 4 5 7

6 10 8 9 12

Abbildung 4.3: L schen des Knoten 7. o

Im Extremfall kann h(T ) gleich n 1 sein, der Aufwand dann also O(n). Deswegen werden wir die Operationen so verbessern, dass h(T ) klein bleibt. Die daf r entscheidenden Operationen sind die u Rotationen, mit denen die Gestalt eines Baumes ver ndert werden kann um die H he klein zu halten. a o Wir unterscheiden zwischen Links- und Rechtsrotation, die Linksrotation RotLinks(v, w) um die Knoten v und w, und die dazu symmetrische Rechtsrotation RotRechts(v, w). Beide sind in ist in Abbildung 4.4 dargestellt. Man beachten, dass das Resultat in beiden F llen wieder ein Suchbaum ist, die a Teilb ume T1 , T2 , T3 also korrekt umgeh ngt werden. a a

v w T1 T2 v w T3 T1 T2 RotRechts(v,w) T1 T3 T1 RotLinks(v,w) v

T3 T2 w v

T2

T3

Abbildung 4.4: Linksrotation RotLinks(v,w)

4.1. BASISOPERATIONEN IN SUCHBAUMEN

49

Linksrotation und Rechtsrotation sind in O(1) durchf hrbar, da nur konstant viele Referenzen ge ndert u a werden m ssen. Eine Java-Methode f r die Linksrotation k nnte in etwa wie folgt aussehen: u u o TreeNode rotateLeft (TreeNode v) { TreeNode aux = v.rson; v.rson = aux.lson; aux.lson = v; v = aux; return v; } Diese Anweisungen werden genauer in Abbildung 4.5 erl utert. Die erste Zeile a TreeNode aux = v.rson; setzt die Hilfsreferenz aux auf den rechten Sohn des zu rotierenden Knotens v. Die Zeile v.rson = aux.lson; setzt den rechten Sohn f r den zu rotierenden Knoten v neu. Danach setzt die Zeile u aux.lson = v; den linken Sohn des von aux referenzierten Knotens auf den zu rotierenden Knoten v. Dann wird durch v = aux; v neu gesetzt und schlielich durch return v; v zur ckgegeben. u Der folgende Satz sagt, dass Rotationen ausreichen, um Suchb ume beliebig zu andern und daher a insbesondere ausreichen, um h(T ) klein zu halten. Satz 4.2 Seien T1 , T2 Suchb ume zur selben Schl sselmenge. Dann gibt es eine endliche Folge von a u Rechts- und Linksrotationen, die T1 in T2 transformiert. Beweis: Wir beweisen den Satz durch vollst ndige Induktion nach der Anzahl der Schl ssel. Aba u bildung 4.6 illustriert das Prinzip. F r n = 1 ist nichts zu zeigen, denn zwei B ume mit nur einem u a Schl ssel und der gleichen Schl sselmenge sind gleich. u u

50

KAPITEL 4. SUCHBAUME

v w T1 T2 T3

aux

v w T1 T2 T3

aux

aux w v T3 T1 T2 T1 T2 T3 v w

aux

Abbildung 4.5: Umh ngen der Referenzen bei der Linksrotation RotLinks(v, w). a

F r n = 2 gibt es nur zwei verschiedene Suchb ume zur gleichen Schl sselmenge, die durch genau u a u berf hrt werden k nnen. eine Links- beziehungsweise Rechtsrotation ineinander u u o n n + 1 : Sei T1 der Ausgangsbaum, w(T1 ) seine Wurzel und T1 der linke und T1r der rechte Teilbaum von T1 . Sei T2 der Baum, in den T1 durch Rotationen umgewandelt werden soll. Das Wurzel w(T2 ) von T2 ist, da die beiden B ume die gleiche Schl sselmenge haben, auch in T1 enta u r von T . Auf die Teilb ume von T trifft die Induktionshalten, etwa o.B.d.A. im rechten Teilbaum T1 a 1 1 voraussetzung zu, und wir k nnen daher T1 mit Rotationen so transformieren, dass der transformierte o Baum T1 eine linke Liste wird (siehe Baum links unten in Abbildung 4.6). Entsprechend k nnen o r mit Rotationen so transformieren, dass der transformierte Baum T r eine rechte Liste wird. 1 wir T1 O.b.d.A. war w(T2 ) im rechten Teilbaum von T1 enthalten. Wegen der speziellen Listengestalt der o B ume T1 und T2r k nnen wir durch eine Folge von Linksrotationen um die Wurzel des ganzen Baua mes daf r sorgen, dass w(T2 ) die Wurzel wird (siehe Baum rechts unten in Abbildung 4.6). u Wegen der Suchbaumeigenschaft haben die Teilb ume T und T r des so entstehenden BaumesT mit a Wurzel w(T2 ) dieselben Schl ssel wie T2 und T2r . Nach Induktionsvoraussetzung k nnen wir daher u o r in T r uberf hren. mit Rotationen T in T2 und T u 2 Die Zusammensetzung dieser Folgen von Rotationen (zun chst Teilb ume von T1 zu Listen, dann a a r ) liefert dann die gew nschte Folge von w(T2 ) an die Wurzel, dann Teilb ume von T zu T2 und T2 a u Rotationen, die T1 in T2 uberf hrt. u

4.2. LITERATURHINWEISE
5 6

51

Abbildung 4.6: Illustration des Beweises von Satz 4.2.

Rotationen reichen also aus, um Suchb ume zu balancieren. Wir denieren daher: a Eine Klasse T von Suchb umen heit balanciert zur H he f (n), wenn gilt: a o 1. Jede Schl sselmenge mit n Knoten (n = 1, 2, . . . ,) kann durch einen Suchbaum T T dargestellt u werden und es gilt h(T ) f (n). 2. Basisoperationen k nnen f r T T in O(h(T )) durchgef hrt werden. o u u 3. Die Klasse T ist abgeschlossen gegen ber Basisoperationen, d.h. Einf gen und L schen in u u o T T f hren wieder zu einem Baum in T. u Gesucht ist eine Klasse von Suchb umen mit f (n) O(log n). Es gibt verschiedene solche Klassen, a die historische alteste ist die der sogenannten AVL-B ume. F r sie ist f (n) 1.4405 log(n + 2) a u 0.3277. Wir werden jedoch nur zeigen, dass f (n) 2 log n gilt.

4.2

Literaturhinweise

Suchb ume werden in jedem Buch uber Datenstrukturen behandelt, vgl. etwa [CLRS01, Knu98, OW02, SS02]. a

52

KAPITEL 4. SUCHBAUME

Kapitel 5

AVL-B ume a
Die historisch alteste Klasse balancierter Suchb ume zur H he f (n) O(log n), die Klasse der AVLa o B ume, wurde 1962 von Adelson-Velski und Landis aus der UdSSR deniert. Die grunds tzliche Idee a a hierbei ist, das Entarten der Suchb ume zu einer Liste durch eine Forderung an die H hendifferenz a o der beiden Teilb ume eines jeden Knotens zu verhindern. Mit dieser Forderung wird erreicht, dass die a H he von f (n) = 1, 44 . . . log n nicht uberschritten wird. o

5.1

Grunds tzliche Eigenschaften a

Um AVL-B ume denieren zu k nnen, ben tigen wir zun chst die Denition der Balance: a o o a Sei T ein bin rer Suchbaum und sei v V ein Knoten. Seien T (v) und Tr (v) die (evtl. leeren Teilb ume) a a von v. Dann heit (v) := h(Tr (v)) h(T (v)) die Balance des Knoten v.
v T (v)
h(T (v)) (v) h(Tr (v))

mit h(0) = 1 /

(5.1)

Tr (v)

Abbildung 5.1: Balance als H hendifferenz o Wie in Abb. 5.1 zu sehen, beschreibt sie die H hendifferenz zwischen dem rechten und linken Teilo baum des Knoten v. Damit k nnen wir AVL-B ume denieren: o a 53

54

KAPITEL 5. AVL-BAUME

Ein bin rer Suchbaum T heit AVL-Baum genau dann, wenn f r alle v V gilt: a u | (v)| 1. (5.2)

Beispiel 5.1 Abbildung 5.2 zeigt die beiden B ume T und T . Die Zahlen an den Knoten geben ihre a Balance an. Bei T handelt es sich um einen AVL-Baum. T erf llt die AVL-Eigenschaft nicht, da die u Balance der Wurzel 2 betr gt. a
T
1

0 1

Abbildung 5.2: Der AVL-Baum T und der Suchbaum T

Aus der Denition von AVL-B umen folgt, dass auch jeder Teilbaum eines AVL-Baums wieder ein a AVL-Baum ist. Wir zeigen nun, dass die Balance-Bedingung daf r sorgt, dass AVL-B ume nicht allzu u a hoch werden. Satz 5.1 Sei T ein AVL-Baum mit n Knoten (n 2). Dann gilt f r seine H he h(T ): u o h(T ) 2 log n (5.3)

Beweis: Um diese Absch tzung zu beweisen, betrachten wir extremale AVL-B ume, die zu vorgegea a bener H he h eine minimale Knotenzahl aufweisen. Sei deshalb o n(h) := min{n | T ist AVL-Baum mit n Knoten und h(T ) = h} (5.4)

Abbildung 5.3 zeigt, wie solche extremalen AVL-B ume aufgebaut sind. Bez glich der Struktur eines a u extremalen AVL-Baumes T , lassen sich daher folgende Eigenschaften vermuten: 1. Die H hendifferenz der Teilb ume eines extremalen AVL-Baumns ist 1 oder 1 (auer der o a Baum hat nur einen Knoten). 2. Die Teilb ume T und Tr eines extremalen AVL-Baums der H he h 1 sind selber wieder a o extremale AVL-B ume zu den H hen h 1 und h 2 bzw. h 2 und h 1. a o Wir wollen nun diese Vermutungen beweisen:

5.1. GRUNDSATZLICHE EIGENSCHAFTEN


h 0 1 2 ... 3 ... ... ...

55

Abbildung 5.3: Extremale AVL-B ume. a zu 1.: Angenommen, T sei ein extremaler AVL-Baum mit einer H hendifferenz 0. Nimmt man nun, o a wie in Abb. 5.4, im linken Teilbaum alle Bl tter weg, ergibt sich wieder ein AVL-Baum, da das L schen der Bl tter die Balancebedingung | (u)| 1 f r alle u V nicht verletzt. Dieser o a u AVL-Baum hat dieselbe H he, aber weniger Knoten als T . Damit ist T nicht mehr extremal. o Das ergibt einen Widerspruch. zu 2.: Da nach Denition von AVL-B umen klar ist, dass alle Teilb ume von AVL-B umen wieder a a a AVL-B ume sind, bleibt zu zeigen, dass seine Teilb ume extremal zu den H hen h 1 und a a o h 2 sind. Angenommen, T sei extremal, aber ein Teilbaum, o.B.d.A. T , nicht. Dann gibt es einen AVL-Baum T mit weniger Knoten als T , aber derselben H he. Ersetze nun T durch T o in Baum T . Damit ergibt sich ein neuer Baum T mit weniger Knoten, aber derselben H he. o o a o Da T und Tr beides AVL-B ume sind und die H he von T gleich der H he von T ist, sich also die Balance in der Wurzel nicht andert, ist auch T ein AVL-Baum. Da dieser aber weniger Knoten hat als T , kann T nicht extremal sein. Das ergibt einen Widerspruch. Also sind die Teilb ume von T extremal. Dass sie die H hen h 1 und h 2 haben, ergibt sich aus der ersten a o Vermutung.

T
1 0 1 1

Abbildung 5.4: L schen der Bl tter im linken Teilbaum o a Die bewiesene Vermutung f hrt zu der zentralen Rekursionsformel f r die Knotenzahl extremaler u u AVL-B ume in Abh ngigkeit von der H he: a a o n(0) = 1, n(1) = 2 n(h) = n(h 2) + n(h 1) + 1 f r h 2 u (5.5)

56

KAPITEL 5. AVL-BAUME

Dabei wird zu der Anzahl der Knoten der beiden Teilb ume noch ein Knoten f r die Wurzel addiert. a u Aus der Rekursionsformel 5.5 folgt dann dieses Lemma: Lemma 5.1 F r die minimale Knotenzahl n(h) eines AVL-Baumes der H he h, (h 0) gilt: u o n(h) 2 2 Beweis: (vollst ndige Induktion nach h) a Induktionsanfang: h = 0 = n(h) = 1 = 20 = 2 2 h h = 1 = n(h) = 2 2 = 2 2 h h = 2 = n(h) = 4 2 = 2 2 Induktionsschritt von h 1 auf h: Sei also das Lemma bewiesen f r 1, 2, . . . , h 1. Dann folgt: u n(h) = n(h 1) +n(h 2) + 1
5.5 5.5
h h

(5.6)

= n(h 2) + n(h 3) + 1 + n(h 2) + 1 > 2n(h 2)


IV
h2 2

22 = 2
h

h2 2 +1 h

= 22 Zwar ist hier n(h) echt gr er als 2 2 , aber f r h = 0 ist n(h) gleich 2 2 . Deswegen ist n(h) 2 2 . o u
h h

Aus dem Lemma folgt dann durch Logarithmieren: log n(h) h 2 h 2 log n(h) h 2 log n(T ) f r jeden AVL-Baum T mit n(T ) Knoten und der H he h(T ). u o

Um zu beweisen, dass h 1, 44 . . . log n ist, benutzt man diesen Ansatz: Die Rekursionsformel 5.5 ahnelt der der Fibonacci-Folge: f0 = 0, f1 = 1 fi = fi1 + fi2

5.2. ROTATIONEN i 0 1 2 3 4 5 6 7 . . . n(i) fi 1 0 v 2 v 1 4 vvv 1 v 7 vvv 2 v v3 12 v v 20v vv 5 v 33v vv 8 v 54 vv 13 . v . . . . .

57

Abbildung 5.5: Zusammenhang zwischen Rekursionsformel 5.5 und der Fibonacci-Folge. Daher nennt man extremale AVL-B ume auch Fibonacci-B ume. Den genauen Zusammenhang zwia a schen diesen beiden Folgen zeigt die Tabelle in Abbildung 5.5. Es ist leicht zu sehen, dass fi = n(i 3) + 1. Damit kann man n(h) analog zu der Fibonacci-Folge in geschlossener Form absch tzen. Die Formel f r die Fibonacci-Zahlen lautet: a u n n 1+ 5 1 5 fi = , wobei = und = 2 2 5 Daraus folgt dann (mit etwas Arbeit) die obige genauere Absch tzung. Wir verzichten hier auf den a genauen Beweis.

5.2

Rotationen

Um die schon bei Suchb umen angesprochenen Basisoperationen durchf hren zu k nnen, ohne den a u o AVL-Baum auer Balance zu bringen, ben tigt man Rotationen. Im letzten Kapitel uber Suchb ume o a wurden bereits die einfachen Rotationen RotLinks(v, w) und RotRechts(v, w) erkl rt. Neben diesen a benutzt man bei AVL-B umen noch die Doppelrotationen. Zur Erkl rung beschr nken wir uns auf a a a eine anschauliche Darstellung in den Abbildungen 5.6 und 5.7: Die Doppelrotationen haben diese Eigenschaften: 1. Der nach der Doppelrotation resultierende bin re Baum T ist wiederum ein Suchbaum. a 2. Die Doppelrotationen lassen sich durch die einfachen Rotationen RotLinks und RotRechts ausdr cken: u DRotLinks (v, v , v ) = RotLinks (v, v ) RotRechts (v , v ) und DRotRechts (v, v , v ) = RotRechts (v, v ) RotLinks (v , v ) . Rotationen und Doppelrotationen reichen aus, um AVL-B ume nach dem L schen bzw. Einf gen a o u eines Knotens zu rebalancieren. Basis hierf r ist das folgende Lemma: u

58
v
2

KAPITEL 5. AVL-BAUME
v

v
1

T1 T4 T2 T3
Abbildung 5.6: Doppellinksrotation DRotLinks(v, v , v ).
v
2

T1

T2

T3

T4

v
1

=
T4 T1 T2 T3 T4

T1 T2 T3

Abbildung 5.7: Doppelrechtsrotation DRotRechts(v, v , v ). Lemma 5.2 (Rotationslemma fur AVL-B ume) Sei T ein Baum mit Wurzel v. Der linke und der a rechte Teilbaum T , Tr von T seien AVL-B ume. Die Wurzel v sei geringf gig auer Balance, d.h. a u | (v)| = 2. Dann folgt: a) T kann durch eine Rotation bzw. Doppelrotation in einen AVL-Baum T uberf hrt werden mit u h(T ) h(T ). b) Die Art der Rotation (einfach links, . . . , doppelt rechts) kann mit O(1) Aufwand ermittelt werden. c) Die Rotation kann in O(1) Aufwand durchgef hrt werden. u d) Alle ver nderten Balancen in T k nnen mit O(1) Aufwand aus denen in T berechnet werden. a o

5.2. ROTATIONEN Beweis: Wir unterscheiden 4 F lle: a

59

1.) Der Weg von v in die gr te Tiefe geht links links (LL) o

T
v

T =
T3

2 1

T1 T2 T3

T1

T2

Abbildung 5.8: Rechtsrotation bei dem Fall LL. Aus Abbildung 5.8 folgt: (v) = 2 und (v ) {0, 1}. Durch Anwenden der Rechtsrotation RotRechts(v, v ) auf T entsteht T : F r die Balancen in T gilt offenbar: u (v) = 1 falls (v ) = 0 0 falls (v ) = 1 (5.7)

(v ) =

1 falls (v ) = 0 0 falls (v ) = 1

(5.8)

(u) = (u) , f r alle u = v, v u Ferner ist h(T ) = h(T ) falls (v ) = 0 h(T ) 1 falls (v ) = 1

(5.9)

(5.10)

Da f r alle u V gilt, dass | (u)| 1 ist und h(T ) h(T ) ist, folgt sofort Aussage a). Die beiden u Balancen f r v und w bestimmen nun die Art der Rotation. Die Balancen k nnen leicht in O(1) u o ermittelt werden. Also folgt Aussage b). Dass die Rotation mit einem Aufwand von O(1) durchf hrbar u ist und somit Aussage c) stimmt, wurde bereits im letzten Kapitel bewiesen. Aussage d) stimmt, weil sich die ver nderten Balancen mit den obigen Gleichungen in O(1) bestimmen lassen. a

60

KAPITEL 5. AVL-BAUME

T
V

=
v T4
2 1

T1

T2

T3

T4

T1 T2 T3

Abbildung 5.9: Doppelrechtsrotation bei dem Fall LR und nicht LL. 2.) Weg von v in die gr te Tiefe geht links rechts und nicht links links (LR) o F r diesen Fall gilt: (v) = 2, (v ) = 1 und (v ) {1, 0, 1}. Wendet man die Doppelrechtsrou tation DRotRechts(v, v , v ) an, entsteht T . F r ihn gilt: u 0 falls (v ) = 0 0 falls (v ) = 1 (v ) = 0 falls (v ) = 1 0 falls (v ) = 0 1 falls (v ) = 1 (v ) = 0 falls (v ) = 1 0 falls (v ) = 0 0 falls (v ) = 1 (v) = 1 falls (v ) = 1 (u) = (u) , f r alle u = v, v , v u Ferner ist h(T ) = h(T ) 1 Daraus ergeben sich analog zum 1. Fall die Aussagen a), b), c) und d). (5.15)

(5.11)

(5.12)

(5.13)

(5.14)

3.) Weg von v in die gr te Tiefe geht rechts - rechts (RR) o Dieser Fall ist symmetrisch zum 1. Fall mit einer Linksrotation und wird analog bewiesen.

5.3. DIE BASISOPERATIONEN IN AVL-BAUMEN 4.) Weg von v in die gr te Tiefe geht rechts - links und nicht rechts - rechts (RL) o Dieser Fall ist symmetrisch zum 2. Fall mit einer Doppellinksrotation und wird analog bewiesen.

61

Hierbei ist unbedingt zu beachten: Geht der Weg in die gr te Tiefe sowohl LL als auch LR (1. Fall), o so erzeugt eine Doppelrotation DRotRechts im Allgemeinen keinen AVL-Baum, wie das Beispiel in Abbildung 5.10 zeigt. Dies gilt nat rlich ebenso f r den symmetrischen Fall. u u

T DRotRechts(6, 3, 4)

=
2

6 7

(3) = 2 kein AVL-Baum

=
T
3 2

RotRechts(6, 3)

AVL-Baum

Abbildung 5.10: Die unterschiedlichen Rotationen bei LL und LR.

5.3

Die Basisoperationen in AVL-B umen a

Zur efzienten Durchf hrung der Basisoperationen Suchen, Einf gen und L schen muss jeder Knoten u u o u seine Balance (u) kennen, d.h., wir setzen voraus, dass sie in jedem Knoten u V abgespeichert ist. Die Basisoperationen werde zun chst wie in allgemeinen Suchb umen durchgef hrt, danach wird a a u ggf. durch Rotationen die AVL-Eigenschaft wieder hergestellt und werden die neuen Balancen f r die u

62 Knoten mit ver nderter Balance ermittelt und abgespeichert. a

KAPITEL 5. AVL-BAUME

5.3.1

Suchen eines Knotens v

Die Suchen eines Knotens in einem AVL-Baum entspricht der normalen Suche in einem Suchbaum, da die Struktur des Baumes unver ndert bleibt. Die AVL-Eigenschaft bleibt also erhalten. Da der a Aufwand f r diese Basisoperation im Suchbaum in O(h(T )) liegt, folgt f r den AVL-Baum, dass das u u Suchen in O(log n(T )) arbeitet.

5.3.2

Einfugen eines neuen Knotens v

Zun chst muss der Platz gesucht werden, an dem der neue Knoten entsprechend der Suchbaumeia genschaft eingef gt werden soll. Den dabei gegangenen Weg von der Wurzel bis zu der Einf gestelle u u nennen wir die Spur. Dann wird der Knoten an der entsprechenden Stelle eingef gt und es ergibt sich u ein neuer Baum T . Der Aufwand hierf r liegt in O(h(T )) = O(log n(T )). u Beim Ubergang von T zum neuen Baum T kann allerdings die AVL-Eigenschaft verloren gehen, aber nur entlang der Spur zur Wurzel. Alle anderen Teilb ume bleiben gleich und es gilt (u) = (u) f r a u alle Knoten u, die nicht auf der Spur liegen, wobei und die Balancen in den B umen T und a T sind. Also sind nur die Balancen entlang der Spur zu pr fen und gegebenenfalls in Ordnung zu u bringen. Wie dies geschieht, zeigt der folgende Algorithmus. Algorithmus 5.1 Rebalancieren beim Einf gen: u (i) Setze (v) = 0, da v ein Blatt ist. (ii) Akualisiere die Balance (u) des Vaters u von v. (iii) Gilt | (u)| 1 und u = root, so setze v := u und gehe zu (ii). (iii) Ist | (u)| = 2, so folgt: // Beide Teilb ume sind noch AVL-B ume a a // Die Situation aus dem Rotationslemma (Lemma 5.2) liegt vor. F hre eine entsprechende Rotation bzw. Doppelrotation durch, die die Balance wieder heru stellt und aktualisiere die Balancen. // War w der Vater von u vor der Rotation, so setze v := w und gehe zu (ii). Dabei gilt: Satz 5.2 Wird beim Einf gen von v eine Rotation bzw. Doppelrotation in v1 ausgef hrt, so erf llen u u u danach alle Vorg nger u von v1 auf der Spur die Balancebedingung | (u)| 1. a

5.3. DIE BASISOPERATIONEN IN AVL-BAUMEN

63

T
v2

T
v2

v1 w

w v1

2 v

Abbildung 5.11: Nach dem Einf gen gen gt es einmal zu rotieren (doppelt oder einfach), um die u u AVL-Eigenschaft wieder herzustellen.

Beweis: Angenommen, das Einf gen von v erzeugt einen Baum T mit den folgenden Balancen in v1 u und v2 , die auf der Spur von T liegen: (v1 ) = (v2 ) = 2, wobei v1 der erste Knoten (von unten) ist, der auer Balance geraten ist. In T musste also | (v1 )| = 1 und | (w)| = 0 gelten, sonst w re v1 nicht der erste Knoten mit | (v1 )| = a 2. Abh ngig davon, ob v am linken oder am rechten Teilbaum eingef gt wurde, ist entweder eine Dopa u pelrechtsrotation oder eine einfache Rechtsrotation notwendig, um v1 in Balance zu bringen. Durch Anwendung der Rechtsrotation RotRechts(v1 , w) verringert sich die H he des Teilbaums, der nun die o Wurzel w hat, um 1. Vergleiche dazu den 1. Fall des Rotationslemmas (Lemma 5.2). Doppelrotationen machen nach dem 2. Fall des Rotationslemmas (Lemma 5.2) den entstehenden Teilbaum immer um 1 weniger hoch. Also wird der Teilbaum mit der Wurzel v1 , unabh ngig davon, ob eine einfache a Rechtsrotation oder eine Doppelrechtsrotation durchgef hrt wird, danach durch einen um 1 weniger u hohen Teilbaum ersetzt. Nun ist die Balancebedingung in v2 nicht mehr verletzt, da der Teilbaum ja wieder dieselbe H he hat wie vor dem Einf gen. Die symmetrischen F lle folgen entsprechend. o u a

Daraus folgt insgesamt: Um nach dem Einf gen den Baum zu rebalancieren, gen gt es, entlang der u u Spur soweit nach oben zu gehen, bis zum ersten Mal eine Balanceverletzung (| (u)| = 2) auftritt, und dort die entsprechende Rotation anzuwenden. Also ist nur eine Rotation bzw. eine Doppelrotation n tig, aber die Stelle ist m glicherweise erst an o o der Wurzel. Das bedeutet, dass der Aufwand in O(h(T )) = O(h(T )) = O(log n(T )) liegt.

Beispiel 5.2 Betrachte das sukzessive Einf gen von 4, 5, 7, 2, 1, 3, 6 ausgehend von einem leeren Baum: u

64

KAPITEL 5. AVL-BAUME

4
0

RR 5 RotLinks(4, 5)
1 0

4 5
0

4 7

2 5
1

1 5
0 2

LL 5 RotRechts(4, 2)
0 0

4
0

7
1

4 2
0

7
0

2
0

7 4

2 1 3 5
1 2

LR 4 DRotRechts(5, 2, 4)
0 0

2
0 1

7
0

2
0

5
0

1
0

4 3

6 4
0

RL 4 DRotLinks(5, 7, 6)
2 0

2
0 0

5
1 0

2
0 0

6
0

3
0

7 6

Abbildung 5.12: Einf gen von Knoten in einen AVL-Baum u

5.3. DIE BASISOPERATIONEN IN AVL-BAUMEN

65

5.3.3

L schen eines Knotens v o

Das L schen (ohne rebalacierende Rotationen) funktioniert wie bei allgemeinen Suchb umen. Es soll o a hier aber trotzdem kurz wiederholt werden: (i) Suche v. Falls v ein Blatt ist oder nur einen Sohn hat, so l sche v und o h nge gegebenenfalls den einen Sohn an den Vater von v. a Die (ii) Falls v zwei S hne hat, so suche im linken Teilbaum den am weitesten rechts stehenden o Knoten u. Tausche die Inhalte von u und v und l sche v. o Schritte (i), (ii) sind in O(h(T )) = O(log n(T )) durchf hrbar. u Sei T der neue Baum. Das L schen des Knotens v kann die Balancen seiner Vorfahren (und zwar o nur der Vorfahren) andern. Also m ssen alle Knoten auf dem Pfad zur Wurzel (der Spur) ausgehend u vom gel schten Knoten untersucht undihre Balancen aktualisiert werden. Tritt dabei in einem Knoten o u eine gest rte Balance auf, ist (u) = 2 und die Teilb ume sind AVL-B ume. Das Rotationslemma o a a (Lemma 5.2) kann also angewendet werden. Dies wird entlang der gesamten Spur durchgef hrt. u

Beispiel 5.3 Betrachte das schrittweise L schen der Knoten 4, 8, 6, 5, 2, 1, 7 ausgehend von einem o AVL-Baum:

5 3 2 1 4 6 7 9 8 10 11

4 2 1 3

5 8 7 6 9 10 11

8 2 1 3

5 7 6 9 10 11

6 2 1 3

5 10 7 9 11

66

KAPITEL 5. AVL-BAUME

5 2 1

3 10 7 9 11

2 3 1

7 10 9 11

1 3

7 10 9 11

7 3

10 11 9

Abbildung 5.13: L schen von Elementen im ausgeglichenen Baum o Das L schen des Knoten mit dem Schl ssel 4 selbst ist einfach, da dieser ein Blatt ist. Es f hrt aber o u u zu einem unausgeglichenen Baum, denn (3) = 2. Die Ausgleichsoperation bedingt eine einfache Rechtsrotation. Ausgleichen wird erneut nach dem L schen von Knoten 6 notwendig. Dieses Mal o kann der Teilbaum mit der Wurzel 7 durch eine einfache Linksrotation ausgeglichen werden. L schen o von Knoten 2 ist zwar selbst eine direkte Operation, da nur ein Nachfolger existiert, es impliziert aber eine Doppellinksrotation. Um den Knoten mit dem Schl ssel 7 zu l schen, wird zun chst die 7 u o a mit dem gr ten Element seines linken Teilbaumes, d.h. mit der 3, vertauscht und dann wird der neue o Knoten mit der 7 gel scht. Schlielich wird durch das L schen dieses Knotens noch eine Linksrotation o o verursacht. Im Allgemeinen muss nach dem L schen, im Unterschied zum Einf gen, mehrmals rebalanciert wero u den. 1 Da aber jede Rotation bzw. Doppelrotation in konstanter Zeit durchf hrbar ist, folgt, dass das u L schen in O(h(T )) = O(log n(T )) m glich ist. Im schlimmsten Fall kann das L schen eines Knoo o o tens sogar eine Rotation f r jeden Knoten entlang der Spur verursachen. Diese Situation ist jedoch ein u eher ungl ckliches Zusammentreffen von Zuf llen. Wie wahrscheinlich sind nun Rotationen im Allu a gemeinen? Das uberraschende Resultat empirischer Tests ist, dass zwar eine Rotation bei etwa jedem zweiten Einf gen, aber nur bei jedem f nften L schen erforderlich ist. L schen in AVL-B umen ist u u o o a daher im Mittel etwa gleich aufw ndig wie Einf gen. a u Insgesamt zeigt sich, dass die Klasse der AVL-B ume balanciert zur H he f (n) = 2 log n ist. a o
1 Aber

auch beim L schen gibt es einige Spezialf lle in denen man mit maximal einer Rotation auskommt (Ubung). o a

5.4. LITERATURHINWEISE

67

Abschlieend ist zu bemerken, dass es auch noch andere Klassen balancierter Suchb ume gibt, die a zur H he 2 log n ausgeglichen sind. Bei ihnen sind sowohl beim Einf gen als auch beim L schen nur o u o O(1) Rotationen durchzuf hren. Dazu geh ren zum Beispiel die Red-Black-Trees. u o

5.4

Literaturhinweise

Balancierte Suchb ume werden in jedem Buch uber Datenstrukturen behandelt. F r AVL-B ume und Reda u a Black-Trees sei auf [CLRS01] verwiesen.

68

KAPITEL 5. AVL-BAUME

Kapitel 6

Optimale statische Suchb ume a


6.1 Statische Suchb ume allgemein a

Bisher haben wir den dynamischen Fall betrachtet, bei dem sich die Schl sselmenge uber die Zeit u andert und deshalb die Operationen L schen und Einf gen n tig sind. Jetzt behandeln wir den stao u o tischen Fall. Hier gibt es eine feste Schl sselmenge, f r die wir die Zugriffswahrscheinlichkeiten u u kennen. Dazu kann man sich vor dem Speichern die richtige Gestalt des Suchbaumes ausw hlen bzw. a konstruieren, um die mittlere Zugriffszeit klein zu halten. In der Praxis werden optimale statische Suchb ume beispielsweise f r das Speichern auf einer CD-Rom verwendet. a u Beispiel 6.1 F r die folgenden Schl ssel mit den entsprechenden Zugriffsh ugkeiten wurden die u u a beiden statischen Suchb ume T1 und T2 in Abbildung 6.1 zum Abspeichern konstruiert. a Schl ssel si u H ugkeit i in % a 1 20 2 5 3 10 4 25 5 10 6 30

T1

T2
2 6 1 4

1 2 4

3 5

Abbildung 6.1: Die beiden statischen Suchb ume T1 und T2 zu Bsp. 6.1 a 69

70

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME

Die mittleren Zugriffszeiten der beiden Suchb ume (in Anzahl von Vergleichen): a F r T1 u 1 10 f r 3 u 2 20 f r 1 u 2 10 f r 5 u 3 5 f r 2 u 3 25 f r 4 u 3 30 f r 6 u 250 F r T2 u 1 30 f r 6 u 2 5 f r 2 u 3 20 f r 1 u 3 10 f r 3 u 4 25 f r 4 u 4 10 f r 5 u 270

Das ergibt also im Mittel 2, 5 Vergleiche bzgl. T1 und 2, 7 Vergleiche bzgl. T2 . Beim optimalen statischen Suchbaum T3 (Abbildung 6.2) aber werden im Mittel nur 1, 95 Vergleiche ben tigt. o

T3

1 3 2 5

Abbildung 6.2: Der optimale statische Suchbaum f r Bsp. 6.1. u Wie ermittelt man nun den optimalen statischen Suchbaum? Um das zu beantworten, m ssen wir erst u kl ren, was optimal uberhaupt heien soll. a

6.2

Optimalit t statischer Suchb ume a a

Zun chst ben tigen wir einige Denitionen. Sei S = {s1 , . . . , sn }, mit s1 < s2 < < sn , die Schl sselmenge, a o u die in einem Suchbaum T abgespeichert werden soll. Seien 1 , . . . , n die Zugriffsh ugkeiten, mit a denen auf die Schl ssel si der Schl sselmenge S zugegriffen wird. Dann ist u u C(T ) := i (1 + hT (si ))
i=1 () n

(6.1)

die Gesamtzugriffszeit f r T . Das C steht dabei f r cost. Der Ausdruck () entspricht der Anzahl u u der Vergleiche, die ben tigt werden, um si zu nden. Sei nun o p= n 1 ,..., i i

6.2. OPTIMALITAT STATISCHER SUCHBAUME die H ugkeitsverteilung. Dann ist a E p (T ) := C(T ) n i i=1

71

(6.2)

die mittlere Zugriffszeit pro Schl ssel. Nun k nnen wir uns der Denition der Optimalit t zuwenden: u o a T heit optimaler statischer Suchbaum f r S und 1 , . . . n , falls u C(T ) C(T ) E p (T ) E p (T ) Satz 6.1 Sei T ein Suchbaum f r S und T ein Teilbaum von T . Dann gilt: u 1. Die Schl sselmenge S der Schl ssel in T bildet eine konsekutive Teilsequenz (Intervall) si < u u si+1 < < s j von s1 < s2 < < sn . 2. Prinzip der optimalen Substruktur Ist T optimal f r S und 1 , . . . , n , so ist T optimal f r die zugeh rige Schl sselmenge S = u u o u {si , si+1 , . . . , s j } und die H ugkeiten i , i+1 , . . . , j ist. a f r alle Suchb ume T u a zu S und 1 , . . . , n

(6.3)

Beweis: zu 1.:

T
Spur zu Wurzel sk von T

sk

Abbildung 6.3: Statischer Suchbaum T mit einem Teilbaum T . Seien si der kleinste Schl ssel in T , s j der gr te Schl ssel in T und sk der Schl ssel in der Wurzel u o u u von T . Sei s S mit si < s < s j . Dann ist zu zeigen, dass s aus der Schl sselmenge S ist, der u Knoten mit dem Schl ssel s also im Teilbaum T liegt. Angenommen, das sei nicht so. Dann sind u zwei F lle zu unterscheiden. a

72 Fall (i): s liegt auf der Spur zu sk .

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME

sk

Sei o.b.d.A. sk im linken Teilbaum von s . Dann w rde aber u folgen, dass s j < s ist, was einen Widerspruch zur Voraussetzung ergibt.

Fall (ii): s liegt auerhalb der Spur zu sk .

sr

sk

Betrachte den kleinsten gemeinsamen Vorfahren sr von sk und s . Sei o.b.d.A. T links von sr . Dann folgt: s j < sr < s , da s rechts von sr liegen muss. damit ergibt sich allerdings ein Widerspruch zur Voraussetzung.

zu 2.:

= +

sk si
i

Abbildung 6.4: Der statische Suchbaum T zur Veranschaulichung von ,

und

Sei

= hT (si ) + 1 = +

, wobei

= hT (si ) + 1 ist und = hT (sk ). Dann gilt:

6.3. KONSTRUKTION EINES OPTIMALEN STATISCHEN SUCHBAUMES

73

C(T ) = 1 = 1

1 + + n n 1 + + i1 i1 j

(Schl ssel vor S =: vorher) u (Schl ssel in S ) u (Schl ssel nach S =: nachher) u + ) j

+ i i + + j + j+1 = + = + + = + = + (
i

vorher

j+1 + + n n

nachher vorher
i

+ )i + + (

nachher vorher + nachher


i

i + +

j + i + + j

i + +
=C(T )

j + (i + + j) (i + + j) +C(T )

vorher + nachher +

unabh ngig von T a

C(T ) = Konstante +C(T ) Ist also T optimal, folgt, dass auch T optimal ist.

Der Satz zeigt, dass sich jeder optimale statische Suchbaum aus optimalen statischen Suchb umen f r a u eine kleinere Schl sselmenge (mit den entsprechenden H ugkeiten) zusammensetzt. Das bedeutet, u a dass optimale statische Suchb ume rekursiv aus kleineren optimalen statischen Suchb umen aufgea a baut werden k nnen. o

6.3

Konstruktion eines optimalen statischen Suchbaumes

Dazu zun chst etwas Notation. Sei Ti j ein Suchbaum f r die Schl ssel si+1 , . . . , s j . Wenn Ti j die Wurzel a u u sk hat, so hat Ti j die Teilb ume Ti,k1 und Tk, j , vgl. Abbildung 6.5. a Dann seien Ci j := C(Ti j ) die Kosten von Ti j und i j := i+1 + + j die Summe der H ugkeiten der a ij u Schl ssel in Ti j . Sei r = hTi j (sr ) + 1 die Anzahl der Vergleiche, um den Knoten mit dem Schl ssel sr u im Teilbaum Ti j zu nden. Damit gilt: Ci j = i+1 = i+1
ij ij i+1 + + j j ij ij ij ij i+1 + + k1 k1 + k (0 + 1) + k+1 k+1 + + j j

74

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME

Ti, j

Sk

Ti,k1

Tk, j

Abbildung 6.5: Der statische Suchbaum Ti j mit der Wurzel sk Da die Teilb ume Ti,k1 und Tk, j den gemeinsamen Vater sk und daher alle Knoten in ihnen eine um 1 a geringere H he als im Baum Ti, j haben, gilt dann: o Ci j = i+1 ( =
kj kj i,k1 i,k1 i+1 + 1) + + k1 ( k1 + 1) + k + k+1 ( k+1 + 1) + + j ( j + 1) i,k1 i+1 ( i,k1 ) + i+1 + + k1 ( k1 ) + k1 + k i+1 +k+1 ( k j ) + k+1 + + j ( k j ) + j j k+1 i,k1 i,k1 i+1 ( i+1 ) + + k1 ( k1 ) + i+1 + + k1 +k Ci,k1 i,k1 kj kj k+1 ) + + j ( j ) Ck j

+ k+1 + + j + k+1 (
k j

= Ci,k1 + i,k1 + k + k j +Ck, j


i j

Also ist Ci j = i j +Ci,k1 +Ck j . Die Kosten f r den Teilbaum Ti j mit der Wurzel sk ergeben sich also u aus der Summe der H ugkeiten in Ti j , den Kosten f r den linken Teilbaum Ti,k1 und den Kosten f r a u u den rechten Teilbaum Tk j . Seien nun Ci j opt die Kosten eines optimalen statischen Suchbaumes f r die Schl ssel si+1 , . . . , s j . Sie u u lassen sich wegen Satz 6.1 folgendermaen berechnen: Ci j opt =
k=i+1,..., j

min

i j +Ci,k1 opt +Ck j opt

(6.4)

Jeder Schl sselwert der Schl sselmenge wird als Wurzel ausprobiert und es werden jeweils die Kosten u u der optimalen Teilb ume ermittelt, um sie zu der Summe der H ugkeiten zu addieren. Der optimale a a Baum hat dann den Schl sselwert als Wurzel, f r den die Kosten am geringsten sind. Diese Rekursiu u onsformel wird dann zur Konstruktion von optimalen statischen Suchb umen verwendet. Sie ahnelt a der Bellman-Gleichung des K rzeste-Wege-Problems. Das folgende Beispiel illustriert die Konstruku tion. Beispiel 6.2 Konstruktion eines optimalen statischen Suchbaums: i si i 1 1 0, 1 2 2 0, 1 3 3 0, 2 4 4 0, 05 5 5 0, 3 6 6 0, 25

( i = 1)

6.3. KONSTRUKTION EINES OPTIMALEN STATISCHEN SUCHBAUMES Intervalll nge 0: a Cii opt = 0 Intervalll nge 1: a C0,1 opt C1,2 opt C2,3 opt C3,4 opt C4,5 opt C5,6 opt = = = = = = 0,1 +C0,0 opt +C1,1 opt 1,2 +C1,1 opt +C2,2 opt 2,3 +C2,2 opt +C3,3 opt 3,4 +C3,3 opt +C4,4 opt 4,5 +C4,4 opt +C5,5 opt 5,6 +C5,5 opt +C6,6 opt = = = = = = 0,1 1,2 2,3 3,4 4,5 5,6 = = = = = = 1 2 3 4 5 6 = = = = = = 0, 1 0, 1 0, 2 0, 05 0, 3 0, 25 f r alle i u

75

Der zugeh rige Baum besteht jeweils nur aus der Wurzel. o Intervalll nge 2: a C0,2 opt =
k=1,2

min 0,2 +C0,k1 opt +Ck,2 opt

= min 0, 2 +C0,0 opt +C1,2 opt ; 0, 2 +C0,1 opt +C2,2 opt = min [0, 2 + 0 + 0, 1; 0, 2 + 0, 1 + 0] = 0, 3 (f r k = 1 oder k = 2) u

Da der Baum f r beide k optimal ist, kann zwischen den beiden M glichkeiten gew hlt werden. Der u o a zugeh rige Baum T0,2 f r k = 1 sieht dann so aus: o u
s1 s1

T0,2

=
T0,0 T1,2

=
s2

C1,3 opt

k=2,3

min 1,3 +C1,k1 opt +Ck,3 opt

= min 0, 3 +C1,1 opt +C2,3 opt ; 0, 3 +C1,2 opt +C3,3 opt = min [0, 3 + 0 + 0, 2; 0, 3 + 0, 1 + 0] = 0, 4 (f r k = 3) u
s3 s3

T1,3

=
T1,2 T3,3

=
s2

76 C2,4 opt =

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME min 2,4 +C2,k1 opt +Ck,4 opt

k=3,4

= min 0, 25 +C2,2 opt +C3,4 opt ; 0, 25 +C2,3 opt +C4,4 opt = min [0, 25 + 0 + 0, 05; 0, 25 + 0, 2 + 0] = 0, 3 (f r k = 3) u
s3 s3

T2,4

=
T2,2 T3,4

=
s4

C3,5 opt

k=4,5

min 3,5 +C3,k1 opt +Ck,5 opt

= min 0, 35 +C3,3 opt +C4,5 opt ; 0, 35 +C3,4 opt +C5,5 opt = min [0, 35 + 0 + 0, 3; 0, 35 + 0, 05 + 0] = 0, 4 (f r k = 5) u
s5 s5

T3,5

=
T3,4 T5,5

=
s4

C4,6 opt

k=5,6

min 4,6 +C4,k1 opt +Ck,6 opt

= min 0, 55 +C4,4 opt +C5,6 opt ; 0, 55 +C4,5 opt +C6,6 opt = min [0, 55 + 0 + 0, 25; 0, 55 + 0, 3 + 0] = 0, 8 (f r k = 5) u
s5 s5

T4,6

=
T4,4 T5,6

=
s6

Bei den zweielementigen B umen ist das Ergebnis klar, da von den beiden Knoten der mit der gr eren a o Wahrscheinlichkeit die Wurzel bildet.

6.3. KONSTRUKTION EINES OPTIMALEN STATISCHEN SUCHBAUMES Intervalll nge 3: a C0,3 opt =
k=1,2,3

77

min 0,3 +C0,k1 opt +Ck,3 opt


k=1,2,3

= 0,3 + min C0,k1 opt +Ck,3 opt = 0,3 + min C0,0 opt +C1,3 opt ; C0,1 opt +C2,3 opt ; C0,2 opt +C3,3 opt = 0, 4 + min [0 + 0, 4; 0, 1 + 0, 2; 0, 3 + 0] = 0, 4 + 0, 3 = 0, 7 (f r k = 2 oder k = 3) u In der Abbildung des entsprechenden Baumes wurde k = 2 gew hlt: a
s2 s2

T0,3

=
T0,1 T2,3

=
s1 s3

C1,4 opt

= 1,4 + min C1,k1 opt +Ck,4 opt


k=2,3,4

= 1,4 + min C1,1 opt +C2,4 opt ; C1,2 opt +C3,4 opt ; C1,3 opt +C4,4 opt = 0, 35 + min [0 + 0, 3; 0, 1 + 0, 05; 0, 4 + 0] = 0, 35 + 0, 15 = 0, 5 (f r k = 3) u
s3 s3

T1,4

=
T1,2 T3,4

=
s2 s4

C2,5 opt

= 2,5 + min C2,k1 opt +Ck,5 opt


k=3,4,5

= 2,5 + min C2,2 opt +C3,5 opt ; C2,3 opt +C4,5 opt ; C2,4 opt +C5,5 opt = 0, 55 + min [0 + 0, 4; 0, 2 + 0, 3; 0, 3 + 0] = 0, 55 + 0, 4 = 0, 5 (f r k = 5) u
s5 s5

T2,5

=
T2,4 T5,5

s3 s4

78 C3,6 opt

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME = 3,6 + min C3,k1 opt +Ck,6 opt
k=4,5,6

= 3,6 + min C3,3 opt +C4,6 opt ; C3,4 opt +C5,6 opt ; C3,5 opt +C6,6 opt = 0, 6 + min [0 + 0, 8; 0, 05 + 0, 25; 0, 4 + 0] = 0, 6 + 0, 3 = 0, 9 (f r k = 5) u
s5 s5

T3,6

=
T3,4 T5,6

=
s4 s6

Intervalll nge 4: a C0,4 opt = 0,4 + min C0,k1 opt +Ck,4 opt

k=1,2,3,4

= o,4 + min C0,0 opt +C1,4 opt ; C0,1 opt +C2,4 opt ; C0,2 opt +C3,4 opt ; C0,3 opt +C4,4 opt = 0, 45 + min [0 + 0, 5; 0, 1 + 0, 3; 0, 3 + 0, 05; 0, 7 + 0] = 0, 45 + 0, 35 = 0, 8 (f r k = 3) u
s3 s3

T0,4

=
T0,2 T3,4

s1 s2

s4

C1,5 opt

= 1,5 + min

k=2,3,4,5

C1,k1 opt +Ck,5 opt

= 1,5 + min C1,1 opt +C2,5 opt ; C1,2 opt +C3,5 opt ; C1,3 opt +C4,5 opt ; C1,4 opt +C5,5 opt = 0, 65 + min [0 + 0, 85; 0, 1 + 0, 4; 0, 4 + 0, 3; 0, 5 + 0] = 0, 65 + 0, 5 = 1, 15 In der Abbildung ist k = 3:
s3 s3

(f r k = 3 oder k = 5) u

T1,5

=
T1,2 T3,5

s2 s4

s5

6.3. KONSTRUKTION EINES OPTIMALEN STATISCHEN SUCHBAUMES C2,6 opt = 2,6 + min C2,k1 opt +Ck,6 opt

79

k=3,4,5,6

= 2,6 + min C2,2 opt +C3,6 opt ; C2,3 opt +C4,6 opt ; C2,4 opt +C5,6 opt ; C2,5 opt +C6,6 opt = 0, 8 + min [0 + 0, 9; 0, 2 + 0, 8; 0, 3 + 0, 25; 0, 85 + 0] = 0, 8 + 0, 55 = 1, 35 (f r k = 5) u
s5 s5

T2,6

=
T2,4 T5,6

s3 s4

s6

Intervalll nge 5: a C0,5 opt = 0,5 + min C0,k1 opt +Ck,5 opt

k=1,2,3,4,5

= 0,5 + min C0,0 opt +C1,5 opt ; C0,1 opt +C2,5 opt ; C0,2 opt +C3,5 opt ; C0,3 opt +C4,5 opt ; C0,4 opt +C5,5 opt = 0, 75 + min [0 + 1, 15; 0, 1 + 0, 85; 0, 3 + 0, 4; 0, 7 + 0, 3; 0, 8 + 0] = 0, 75 + 0, 7 = 1, 45 (f r k = 3) u
s3 s3

T0,5

=
T0,2 T3,5

s1 s2 s4

s5

C1,6 opt

= 1,6 +

k=2,3,4,5,6

min

C1,k1 opt +Ck,6 opt

= 1,6 + min C1,1 opt +C2,6 opt ; C1,2 opt +C3,6 opt ; C1,3 opt +C4,6 opt ; C1,4 opt +C5,6 opt ; C1,5 opt +C6,6 opt = 0, 9 + min [0 + 1, 35; 0, 1 + 0, 9; 0, 4 + 0, 8; 0, 5 + 0, 25; 1, 15 + 0] = 0, 9 + 0, 75 = 1, 65 (f r k = 5) u
s5 s5

T1,6

=
T1,4 T5,6

=
s2

s3 s4

s6

80 Intervalll nge 6: a C0,6 opt = 0,6 + =

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME

min C0,k1 opt +Ck,6 opt k=1,2,3,4,5,6 0,6 + min C0,0 opt +C1,6 opt ; C0,1 opt +C2,6 opt ; C0,2 opt C0,4 opt +C5,6 opt ; C0,5 opt +C6,6 opt (f r k = 5) u

+C2,6 opt ; C0,3 opt +C4,6 opt ;

= 1 + min [0 + 1, 65; 0, 1 + 1, 35; 0, 3 + 0, 9; 0, 7 + 0, 8; 0, 8 + 0, 25; 1, 45 + 0] = 1 + 1, 05 = 2, 05

So ergibt sich dann schlielich der optimale statische Suchbaum f r die gegebene Schl sselmenge mit u u den zugeh rigen H ugkeiten zu o a
s5 s5

T0,6

=
T0,4 T5,6

=
s1

s3 s4 s2

Das Prinzip dieses Algorithmus heit auch dynamische Optimierung oder dynamisches Programmieren.

Aufwand
Abschlieend wollen wir uns noch ansehen, wie aufw ndig der Algorithmus ist. Dazu betrachten wir a die folgende Tabelle, die in Zeile i die Gr enordnung des Aufwands f r die Ermittlung des optimalen o u Baums mit Intervalll nge i angibt. a n n1 n2 . . . 2 1 B ume mit a B ume mit a B ume mit a B ume mit a B ume mit a
n1

1 2 3 . . . n1 n

Knoten Knoten Knoten Knoten Knoten

n1 (n 1) 2 (n 2) 3 . . . 2 (n 1) 1n

i=0 n Summen

(n i) (i + 1)
n n

(n3 )

Der Aufwand des Gesamtalgorithmus betr gt f r n Schl ssel also (n3 ) elementare Schritte; er kann a u u aber durch geschicktere Bestimmung der besten Wurzel auf O(n2 ) elementare Schritte reduziert werden. Da der Aufwand sehr hoch ist, ndet der Algorithmus eigentlich nur dort Anwendung, wo es sich wirklich lohnt, wenn also auf den statischen Suchbaum wirklich sehr oft zugegriffen werden soll.

6.4. LITERATURHINWEISE

81

6.4

Literaturhinweise

Der hier dargestellte Algorithmus wird u.a. in [CLRS01] behandelt. Die Verbesserung auf O(n2 ) geht auf [Knu71] zur ck. u

82

KAPITEL 6. OPTIMALE STATISCHE SUCHBAUME

Kapitel 7

B-B ume a
7.1 Denition und Eigenschaften

Im letzten Kapitel zum Thema B ume soll es um die sogenannten B-B ume gehen. Es gibt untera a schiedliche Ansichten dar ber, wof r das B in B-Baum steht. Die h ugste Interpretation ist, dass es u u a f r balanciert steht, da alle Bl tter auf der gleichen Ebene im Baum stehen. Eine weitere Interpretation u a ist, dass das B nach dem Namen seines Ernders Rudolf Bayer f r Bayer steht. u Die bisher betrachteten Suchb ume wurden nur im Hauptspeicher, also nur zur Laufzeit, genutzt. Jetzt a wollen wir groe Datenmengen im Hintergrundspeicher, wie zum Beispiel auf Festplatten, B ndern, a etc., abspeichern. Das Problem hierbei ist, das der Hintergrundspeicher l ngere Zugriffszeiten auf a einen bestimmten Speicherort hat. Das wirkt sich nat rlich auf die Lese- und Schreibzeit aus. Eine u L sung f r dieses Problem ist es, groe Bl cke von Daten auf einmal zu lesen bzw. zu schreiben. Dabei o u o sind Blockgr en von 211 214 Byte, also 2 16 kB, ublich. Die Bl cke werden in Suchb umen o o a organisiert, wobei ein Block mehrere Datens tze mit ihrem entsprechenden Schl ssel enth lt. Diese a u a Suchb ume nennt man dann B-B ume. Da nun mehrere Datens tze mit unterschiedlichen Schl sseln a a a u in einem Knoten gespeichert sind, werden mehrere Teilb ume in den Knoten ben tigt, um zu den a o richtigen Suchschl sseln verzweigen zu k nnen. Die Anzahl der Teilb ume h ngt von der Anzahl der u o a a Datens tze ab, die in einem Knoten gespeichert sind. In Abbildung 7.1 sind zur Veranschaulichung a zwei Datens tze in einem Knoten mit drei Teilb umen gespeichert. a a

D H

Schl ssel u D

Schl ssel u D aber H

Schl ssel u H

Abbildung 7.1: Dieser B-Baum hat drei Teilb ume a 83

84

KAPITEL 7. B-BAUME

Beispiel 7.1 In Abbildung 7.2 sieht man ein Beispiel eines B-Baumes, bei dem Buchstaben den Datens tzen entsprechen. Diese stellen auch gleichzeitig den Suchschl ssel dar. a u
M DH BC FG JKL NP QTX RS VW YZ

Abbildung 7.2: Beispiel f r einen B-Baum u

Betrachten wir jetzt die genaue Denition von B-B umen der Ordnung t: a 1. Jeder Knoten x kennt die Anzahl n[x] seiner Datens tze a kennt die n[x] Datens tze selbst, die aufsteigend sortiert sind a key1 [x] key2 [x] keyn[x] [x] wei durch die Boolesche Variable lea f [x], ob er ein Blatt ist (true) oder nicht (false) 2. Ist der Knoten x kein Blatt, so enth lt er n[x] + 1 Zeiger (c1 [x], . . . cn[x]+1 [x]) auf seine n[x] + 1 a Kinder 3. Die n[x] + 1 Teilb ume enthalten nur Daten mit Schl sseln, die die Suchbaum-Eigenschaft a u nicht verletzen, d.h.:

x
key1 [x] ... keyn[x] [x]

k1

k2

...

kn[x]

kn[x]+1

k1 key1 [x] k2 keyn[x] [x] kn[x]+1

4. Alle Bl tter haben dieselbe H he. a o 5. Jeder Knoten enth lt mindestens t 1 Datens tze. Die Wurzel kann auch weniger Datens tze, a a a aber mindestens einen, besitzen. Jeder Knoten enth lt h chstens 2t 1 Datens tze. a o a Punkt 5 der Denition zeigt, dass die Speicherausnutzung bei fester Blockgr e und bei fester Gr e o o der Datens tze zwischen 50% und 100% liegt. Es wird Speicherplatz geopfert, damit die Basisopea rationen Suchen, Einf gen und L schen schnell durchgef hrt werden k nnen. Bevor wir uns die Bau o u o sisoperationen genauer ansehen, sch tzen wir erst einmal ab, wieviele Datens tze n in einen B-Baum a a fester H he mindestens passen. Dazu folgender Satz: o

7.1. DEFINITION UND EIGENSCHAFTEN

85

Satz 7.1 F r einen extremalen (knotenminimalen) B-Baum der Ordnung t mit n Datens tzen und einer u a H he h gilt: o n+1 (7.1) n 2t h 1 bzw. h logt 2 Beweis: Betrachte einen extremalen B-Baum der Ordnung t mit n Datens tzen und einer H he h. Da a o in diesem extremalen B-Baum die Knotenzahl minimal zur H he ist und diese aber von der Anzahl der o Datens tze pro Knoten abh ngt, m ssen in jedem Knoten so wenig Datens tze wie m glich stehen. a a u a o Deswegen ist in der Wurzel nur 1 Datensatz und in allen ubrigen Knoten sind t 1 Datens tze. Damit a hat die Wurzel 2 S hne und die anderen Knoten haben jeweils t S hne. o o
1 t 1
t S hne o 0 1 Datensatz in der Wurzel t 1 Datens tze pro Knoten a t 1 Datens tze pro Knoten a t 1 Datens tze pro Knoten a ... 1 +2 (t 1) +2 t (t 1) +2 t 2 (t 1) ...

t 1 t 1 t 1

1 2 3 ...

t 1

t 1

...

t 1

...

t 1

t 1 Datens tze pro Knoten a

+2 t h1 (t 1)

n 1 + 2 (t 1) + 2 t (t 1) + 2 t 2 (t 1) + + 2 t h1 (t 1) = 1 + 2 (t 1) t i = 1 + 2 (t 1) = 2 th 1 n+1 h logt 2
h1

i=0 th 1

t 1

Beispiel 7.2 Illustration der Speicherkapazit t von B-B umen a a Speichert man in einem Block ungef hr 2 kB, dann kann man bei einer ublichen Datensatzgr e von a o Telefonbuchdatens tzen von 100 Byte pro Datensatz maximal 20 Datens tze pro Block speichern. a a Das entspricht der Ordnung t = 10. In einem B-Baum der H he h = 5 kann man bereits 2 105 o 1 200000 Datens tze speichern. Das entspricht dem Telefonbuch einer mittleren Stadt. Da eine a sehr groe Datenmenge bei kleiner H he in B-B umen abgespeichert werden kann, bilden sie die o a Standardtechnik f r groe Datenbanken und f r die File-Organisation auf der Festplatte. u u

86

KAPITEL 7. B-BAUME

7.2
7.2.1

Basisoperationen in B-B umen a


Suchen

Das Suchen entspricht im Groen und Ganzen dem Suchen in bin ren Suchb umen. Der einzige Una a terschied besteht darin, dass die einzelnen Knoten noch durchsucht werden m ssen, bis der gesuchte u Schl ssel oder die Stelle zum Absteigen in den Teilbaum gefunden wurde. u

7.2.2

Einfugen

In B-B umen wird ein neuer Datensatz nur in einem Blatt eingef gt. Das entsprechende Blatt muss a u erst gesucht werden. Das Problem ist, dass das Blatt voll sein k nnte, also 2t 1 Datens tze in diesem o a Blatt stehen k nnten. Um dieses Problem zu vermeiden, wollen wir eine vorsichtige Strategie fahren. o Beim Absteigen soll n mlich daf r gesorgt werden, dass alle Vorfahren des entsprechenden Blattes a u nicht voll sind. Dazu werden unterwegs volle Knoten gesplittet. Dies ist m glich, da die Vorg nger o a der Knoten auf der Spur nicht voll sind, weil sie wegen eben dieser Strategie sonst ja schon gesplittet worden w ren. a
y
...

y =

... k ...

... k ...

...

...

Abbildung 7.3: Splitten eines Knoten x Abbildung 7.3 zeigt, wie das Splitten funktioniert. Es wird in der folgenden Situation beim Einf gen u angewendet. Seien die Knoten x und y auf der Spur zu dem Blatt, in das eingef gt werden soll, und sei y der Vater u von x. Wir wissen, dass y nicht voll ist, denn, wenn er voll gewesen war, wurde er im vorherigen Schritt gesplittet. Es kann also noch mindestens ein Datensatz dazukommen. Sei nun der Knoten x voll. Er hat also 2t 1 Datens tze. Dann wird der mittlere Datensatz k nach oben a an die entsprechende Stelle in Knoten y verschoben. Alle Datens tze aus x, die kleiner gleich k sind, a kommen nun in den Knoten x , der links von k steht und alle, die gr er als k sind, kommen in den o Knoten x , der rechts von k steht. Die beiden Knoten x und x sind nun nicht mehr voll, sondern haben t 1 Datens tze. Danach wird weiter nach dem Blatt gesucht, in dass der neue Datensatz eingef gt a u werden soll und gegebenenfalls wieder gesplittet. Diese vorsichtige Vorgehensweise bewirkt, dass man in einem Durchlauf einf gen kann. Ist speziell u die Wurzel voll, muss diese gesplittet werden. Die neue Wurzel hat dann nur einen Knoten. So w chst a der B-Baum in seiner H he. o Beispiel 7.3 Einf gen in einen B-Baum u

7.2. BASISOPERATIONEN IN B-BAUMEN

87

In den folgenden B-Baum der Ordnung t = 3 sollen nacheinander die Datens tze B, Q, L, und F a eingef gt werden. In jedem Knoten m ssen sich dann mindestens 2 Datens tze benden und d rfen u u a u maximal 5 Datens tze sein. Dabei wird die Position, an der der Knoten eingef gt werden soll, durch a u einen blauen Pfeil angezeigt. Der Datensatz, der durch Splitten eine Ebene nach oben geht, ist blau eingekreist.
GMPX

ACDE B einf gen u

JK

NO

RSTUV

YZ

Das B kann einfach zwischen A und C eingef gt werden, ohne das ein Knoten gesplittet werden muss. u
GMPX

ABCDE Q einf gen u

JK

NO

RSTUV

YZ

Da der Knoten (RSTUV) voll ist, muss er, bevor das Q vor das R eingef gt werden kann, gesplittet u werden. Dabei kommt das T einen Knoten nach oben, also in die Wurzel.
GMPTX

ABCDE L einf gen u

JK

NO

QRS

UV YZ

Das L wird hinter das K eingef gt. Allerdings muss vorher die Wurzel gesplittet werden. Dabei kommt u das P in die neue Wurzel und der Baum wird h her. o
P

GM

TX

ABCDE F einf gen u

JKL

NO

QRS

UV

YZ

88

KAPITEL 7. B-BAUME

Um das F hinter dem E einf gen zu k nnen, muss der Knoten (ABCDE) erst gesplittet werden, wobei u o das C nach oben vor das G wandert.
P

CGM

TX

AB

DEF

JKL

NO

QRS

UV

YZ

Da man in einem Durchlauf einf gen kann, hat das Einf gen von einem Datensatz einen Aufwand von u u O(h).

7.2.3

L schen o

Beim L schen verwenden wir eine ahnlich vorsichtige Strategie, wie beim Einf gen. Sind n mlich o u a Knoten fast leer, d.h. haben sie t 1 Datens tze, so wird die Anzahl der Datens tze erh ht, indem a a o man von einem Nachbarn einen Datensatz borgt oder zwei Knoten miteinander verschmilzt. Algorithmus 7.1 (L schen eines Schlussels s) o Starte die Suche nach dem zu l schenden Schl ssel s. o u 1. Der Schl ssel s ist im momentanen Knoten x und x ist ein Blatt. Dann wird s einfach gel scht. u o (Durch entsprechende Vorbereitung, die weiter unten erkl rt wird, wurde daf r gesorgt, dass x a u gen gend Datens tze enth lt.) u a a 2. Der Schl ssel s ist im momentanen Knoten x und x ist ein innerer Knoten. u (a) Das Kind y von x vor dem Schl ssel s hat mindestens t Datens tze. Finde den Vorg nger u a a s von s in dem Teilbaum mit der Wurzel y. Tausche s und s . L sche s rekursiv. o

x
... s ...

y
...
t

s
(b) Das Kind z von x nach dem Schl ssel s hat mindestens t Datens tze. Gehe entsprechend u a (a) vor. (c) Die Knoten y und z haben beide t 1 Schl ssel. Verschmelze y, s, z zu y , der dann 2t 1 u Datens tze enth lt. Diese Verschmelzung ist m glich, da x mehr als t Schl ssel enth lt. a a o u a L sche s nun rekursiv. o

7.2. BASISOPERATIONEN IN B-BAUMEN

89

x
... s ...

x
...

= y
...
t 1

...
t 1

...

s
2t 1

...

3. Ist der Schl ssel s nicht im momentanen Knoten x, so bestimme die Wurzel y des Teilbaumes, der u s enth lt. Falls y nur t 1 Datens tze enth lt, so wende (a) oder (b) an, um mehr als t Schl ssel a a a u sicherzustellen. Suche dann rekursiv in y weiter. (a) y hat nur t 1 Schl ssel, aber einen Bruder z mit t Schl sseln. Mache einen Schl sseltransfer u u u von z zu y und h nge den entsprechenden Teilbaum um: a

x
... k ...

x
... ...

= y
...
t 1

...
t

y
...
t

z
k ...
t 1

(b) Haben y und alle seine Br der nur t 1 Schl ssel, verschmelze y mit einem Bruder z. u u

x
... k ...

x
...

= y
...
t 1

...
t 1

...

k
2t 1

...

4. Sonderfall: Wenn die Wurzel leer wird, l sche die Wurzel. o Beispiel 7.4 In den folgenden B-Baum der Ordnung t = 3 sollen nacheinander die Datens tze F, M, a G, und D gel scht werden. In jedem Knoten m ssen sich dann mindestens 2 Datens tze benden und o u a d rfen maximal 5 Datens tze sein. Der Pfeil zeigt immer auf den zu l schenden Datensatz. Blaue u a o Knoten werden jeweils zusammen mit dem eingekreisten Datensatz verschmolzen.
P

CGM

TX

AB

DEF

JKL

NO

QRS

UV

YZ

F l schen o

90

KAPITEL 7. B-BAUME

Hier muss der 1. Fall des Algorithmus angewendet werden. Da F in einem Blatt steht, kann es einfach gel scht werden. o
P

CGM

TX

AB

DE

JKL

NO

QRS

UV

YZ

M l schen o
Es trifft Fall (2a) zu. M steht in dem inneren Knoten (CGM). Da der Knoten (JKL) 3 Datens tze a enth lt, wird M mit seinem Vorg nger L (hier blau eingekreist) ausgetauscht. Dann wird M nach dem a a 1. Fall gel scht. o
P

CGL

TX

AB

DE

JK

NO

QRS

UV

YZ

G l schen o
G steht im inneren Knoten (CGL). Da die beiden S hne vor und nach dem G (Knoten (DE) und o (JK)) jeweils nur 2 Datens tze enthalten, m ssen sie zusammen mit dem G entsprechend Fall (2c) a u verschmolzen werden. Dann steht G in einem Blatt und kann einfach wie ublich gel scht werden. o
P

CL

TX

AB

DEJK

NO

QRS

UV

YZ

D l schen o
D steht im Blatt (DEJK). Aber auf der Suche danach stellen wir fest, dass die Knoten (CL) und (TX) jeweils nur 2 Datens tze enthalten. Deswegen m ssen sie zusammen mit dem P aus der Wurzel a u entsprechend Fall (3b) verschmolzen werden. Damit tritt der 4. Fall auf, da die Wurzel leer wird. Sie wird dann einfach gel scht. Nun kann D aus seinem Blatt gel scht werden. o o

7.3. LITERATURHINWEISE
CLPTX

91

AB

EJK

NO

QRS

UV

YZ

Auch das L schen kann also in einem Durchlauf entlang des Weges bis zum Blatt geschehen, also in o O(h) Operationen mit Knoten. Pro Knoten sind dabei maximal 2t 1 Operationen mit Datens tzen a durchzuf hren. Dies ergibt insgesamt den Aufwand von O(h t) f r die Operationen Suchen, Einf gen u u u und L schen in B-B umen. o a

7.3

Literaturhinweise

Die hier gew hlte Darstellung lehnt sich eng an [CLRS01] an. Von dort sind auch die Beispiele entnommen. a

92

KAPITEL 7. B-BAUME

Kapitel 8

Hashing
Hashing ist ein anderes Vorgehen, das auch ohne Baumstrukturen ein efzientes Suchen erm glicht. o Wie bei Bucketsort ist auch hier eine der grunds tzlichen Eigenschaften, dass Hashing nicht auf a paarweisen Vergleichen beruht. Beim Hashing werden die Datens tze in einem Array mit Indizes a 0, . . . , m 1, der sogenannten Hash-Tabelle gespeichert. Wenn wir nun w ssten, dass als Schl ssel nur die Zahlen 0, . . . , N, N N vorkommen, k nnten wir die u u o Schl ssel direkt als Array-Indizes verwenden. Das ist aber im Allgemeinen nicht erf llt. Viel ofter tritt u u der Fall auf, dass die Anzahl der tats chlichen Schl ssel viel kleiner ist als die Anzahl der m glichen a u o Schl ssel. Daher berechnet man sich beim Hashing einen Array-Index aus dem Schl ssel: u u Bezeichne U das Universum aller m glichen Schl ssel und K die Menge der Schl ssel, die auch o u u tats chlich vorkommen. Dann verwendet man eine Hash-Funktion h, h : U {0, . . . , m1}, die jedem a Schl ssel k einen Index h(k) zuordnet, seine Hash-Adresse, und speicher es dort ab. Wenn man das u Element dann in der Hash-Tabelle wiedernden m chte, so berechnet man nach Vorschrift der Hasho Funktion die Hash-Adresse und ndet es dann (idealerweise) in O(1) wieder. Leider ist es im Allgemeinen nicht ganz so einfach: Wenn das Universum der m glichen Schl ssel o u mehr Elemente enth lt als die Hash-Tabelle, kann die Funktion nach dem Schubfachprinzip nicht a injektiv sein. Dann gibt es also zwei verschiedene Schl ssel k1 und k2 , so dass h(k1 ) = h(k2 ). Das u bezeichnet man beim Hashing als Kollision. Der zweite Teil beim Hashing besteht also in der Kollisionsbehandlung, die entweder darin bestehen kann, es zu erlauben, auf einer Hash-Adresse mehrere Elemente zu speichern (Chaining) oder sich bei einer Kollision eine andere Hash-Adresse zu berechnen (Offene Addressierung). Hashing ist ein gutes Beispiel f r einen Kompromiss zwischen den beiden G tefaktoren eines Algou u rithmus (Speicherplatzbedarf und Ausf hrungszeit). Wenn wir beliebig viel Zeit zur Verf gung h tten, u u a k nnten wir einfach alle Elemente sequentiell durchsuchen; und h tten wir beliebig viel Speicherplatz, o a k nnten wir einfach den Schl sselwert als Array-Index nehmen (beziehungsweise das Ergebnis einer o u injektiven Hash-Funktion). Wir wenden uns nun dem Problem zu, eine gute Hash-Funktion zu nden.

93

94

KAPITEL 8. HASHING

U
h(k1 ) h(k4 ) k3 k4 h(k2 ) = h(k5 ) k1 k2 k5 h(k3 ) m1
Abbildung 8.1: Hier werden die Elemente mit den Schl sseln k2 und k5 auf den gleichen Eintrag in u der Hash-Tabelle abgebildet.

8.1

Hash-Funktionen

Was zeichnet also eine gute Hash-Funktion aus? Sie sollte leicht und schnell berechenbar sein die Datens tze m glichst gleichm ig verteilt auf die Hash-Tabelle abbilden a o a deterministisch sein (sonst ndet man seine Schl ssel ja nicht wieder) u Kollisionen vermeiden Es kann ziemlich schwierig sein, eine Hash-Funktion zu nden, die injektiv ist, selbst wenn die Zielmenge kleiner ist als die Ausgangsmenge. Beispiel 8.1 Es gibt 4131 1050 verschiedene Funktionen, die von einer 31-elementigen Menge in eine 41-elementige Menge abbilden; injektiv sind davon aber nur 41 40 39. . . 11 = 41!/10! 1043 , also nur ungef hr jede 10millionste! a Beispiel 8.2 [Geburtstagsparadoxon] Die Frage beim Geburtstagsparadoxon ist: Wieviele Leute m ssen u in einem Raum sein, damit die Wahrscheinlichkeit, dass zwei von ihnen am gleichen Tag Geburtstag 1 haben, h her als 2 ist? (Das Jahr hat dabei 365 Tage, wir ber cksichtigen keine Schaltjahre.) o u Das l sst sich auf folgende Art berechnen: a Sei m die Anzahl der m glichen Tage und k die Anzahl der Personen. Die Wahrscheinlichkeit q, dass o es keine Kollision gibt (also, dass alle Personen an verschiedenen Tagen Geburtstag haben), ist dann q(m, k) = m (m 1) (m 2) (m 3) (m k + 1) m! = mmmmm (m k)! mk

8.1. HASH-FUNKTIONEN Dann gilt

95

1 2 Es gen gen also schon 23 Leute, damit die Wahrscheinlichkeit, dass zwei von ihnen am gleichen Tag u Geburtstag haben, gr er als 1 ist. o 2 q(365, 23) 0, 49270276567601459277458277 < Beispiel 8.2 ubertragen auf Hash-Funktionen bedeutet folgendes: Haben wir ein Universum von 23 Schl sseln, eine Hash-Tabelle mit 365 Eintr gen und eine zuf llige Hash-Funktion, so ist die Wahru a a scheinlichkeit, dass zwei Schl ssel auf den gleichen Eintrag in der Hash-Tabelle abgebildet werden, u 23 gr er als 1 . Und dabei haben wir nur eine Auslastung der Hash-Tabelle von 365 6, 301%. o 2 Wir nehmen im Folgenden an, dass die Schl sselwerte nat rliche Zahlen sind; andernfalls kann man u u eine bijektive Funktion nden, die von den Schl sselwerten in eine Teilmenge der nat rlichen Zahlen u u abbildet. (Wir nehmen also an, dass U h chstens abz hlbar viele Elemente enth lt.) o a a

8.1.1

Divisionsmethode

Bei der Divisionsmethode wird f r festes m N folgende Hash-Funktion verwendet: u h : U {0, . . . , m 1}, h(k) := k mod m

In diesem Fall sind einige Werte von m aber besser als andere. Wenn zum Beispiel m gerade ist, so wird h(k) genau dann gerade sein, wenn k schon gerade war. Auerdem sollte man ber cksichtigen, u dass wir im Bin rsystem rechnen. Daher ist es ung nstig, wenn m eine Potenz von 2 ist (m = 2 p ), weil a u dann bei der Berechnung des Hash-Werts von k nur die letzten p Bits ber cksichtigt werden (nat rlich u u kann man diese Hash-Funktion verwenden, wenn man wei, dass alle 1-0-Verteilungen in den letzten p Bits gleich wahrscheinlich sind). Es wird empfohlen, f r m eine Primzahl zu verwenden, die keine der Zahlen ri j teilt, wobei i, j N u kleine Zahlen und r die Basis des Zahlensystems ist. Das ist im Allgemeinen eine gute Wahl.

8.1.2

Multiplikationsmethode

Sei 0 < A < 1 beliebig, aber fest. Dann benutzt man bei der Multiplikationsmethode folgende HashFunktion: h : U {0, . . . , m 1}, h(k) := m(kA mod 1) = m(kA kA )

Es wird also k mit einer Konstante A zwischen 0 und 1 multipliziert, die Vorkommastellen werden abgeschnitten, das Ergebnis wird mit m multipliziert (der dabei entstehende Wert q ist R und es gilt 0 q m). Dann wird abgerundet und wir erhalten einen ganzzahligen Wert q mit 0 q m 1. Dabei ist die Wahl von m nicht so entscheidend wie bei der Divisionsmethode. Nach [Knu98] f hrt dabei eine Wahl von u A ( 5 1)/2 = 0.6180339887 . . .

96 zur gleichm igsten Verteilung von allen Zahlen zwischen 0 und 1. a

KAPITEL 8. HASHING

8.2
8.2.1

Kollisionsbehandlung
Chaining

Beim Chaining steht in der Hash-Tabelle an jeder Stelle eine Liste. Tritt nun beim Einf gen eine u Kollision auf, so werden beide Elemente in die Liste an dieser Stelle geh ngt. Beim Suchen muss a dann nachdem die Hash-Funktion die Stelle berechnet hat, an der das gesuchte Element zu nden ist die dortige Liste noch durchsucht werden.

U
k1 k4 k3 k6 k4 k1 k7 k5 m1
Abbildung 8.2: Beim Chaining enth lt jeder Eintrag der Hash-Tabelle eine Liste der Elemente, die a auf diese Stelle gehasht wurden. Sei h die benutzte Hash-Funktion. Wir betrachten die drei Operationen, die wir durchf hren wollen: u Einfugen Beim Einf gen k nnen wir annehmen, dass das Element nicht bereits in der Hash-Tabelle u o T vorhanden ist; falls es n tig sein sollte, das zu uberpr fen, k nnen wir vorher das Element o u o suchen. Die Einf gen-Methode hat also die Form u chainedHashInsert(T,x) fge x am Kopf der Liste T[h(x.key)] ein u Die Worst-Case-Laufzeit f r das Einf gen ist also O(1). u u Suchen chainedHashSearch(T,k) suche in der Liste T[h(k)] nach einem Element x mit x.key==k Die Worst-Case-Laufzeit vom Suchen ist also von der L nge der Liste abh ngig. a a

k6 k5

k7

k2 k3

K
k2

8.2. KOLLISIONSBEHANDLUNG L schen chainedHashDelete(T,x) o lsche x aus der Liste T[h(x.key)] o

97

Wenn wir das Element bereits gesucht haben und eine doppelt verkettete Liste verwenden, so k nnen wir es nach der Suche in O(1) l schen. o o Wir betrachten jetzt den Aufwand f r das Suchen etwas genauer. Dazu geben wir erst einmal eine u Denition: Sei T eine Hash-Tabelle mit m N Pl tzen, die gerade N n > 0 Elemente speichert. Dann denieren a wir den Auslastungsfaktor der Tabelle als n = m Weil beim Chaining auch mehr Elemente gespeichert werden k nnen als die Hash-Tabelle Eintr ge o a hat, kann hier auch gr er als 1 sein. Das Worst-Case-Verhalten von Hashing mit Chaining tritt o dann auf, wenn alle Elemente auf den gleichen Eintrag der Hash-Tabelle abgebildet werden. Dann hat das Suchen die gleiche Laufzeit wie bei einer einfach verketteten Liste, also (n). Wir wollen nun das Durchschnittsverhalten von Hashing analysieren. Dazu treffen wir folgende Annahme: Gleichverteilungsannahme: Die Wahrscheinlichkeit, dass ein Schl ssel k auf die Adresse i in der u 1 Hash-Tabelle abgebildet wird, ist unabh ngig von i stets gleich m und h ngt nicht davon ab, welche a a Elemente bereits in der Tabelle gespeichert sind. Wir nehmen an, dass der Wert der Hash-Funktion in O(1) berechnet werden kann und die Suchdauer daher von der L nge der Liste dominiert wird. Der Erwartungswert f r die L nge der Liste ist unter a u a der Gleichverteilungsannahme offenbar gleich . Satz 8.1 Beim Hashing mit Chaining ist unter der Gleichverteilungsannahme der Aufwand f r das u Suchen im Mittel O(1 + ). Beweis: Wegen der Gleichverteilungsannahme wird Schl ssel k mit gleicher Wahrscheinlichkeit auf u jeden der Eintr ge gehasht. Wir k nnen den Wert der Hash-Funktion in O(1) berechnen. Wir speia o chern die Elemente in der Hash-Tabelle in Listen. Diese haben eine mittlere L nge von . Daher ist a der Aufwand f r eine Suche im Mittel und damit der Aufwand f r das Suchen O(1 + ). u u

Korollar 8.1 Falls m proportional zu n ist, also n = O(m) gilt, ist der Aufwand f r das Suchen im u Mittel konstant. Da das Einf gen und L schen (nach dem Suchen) in O(1) gehen, k nnen daher alle u o o drei Operationen im Mittel in konstanter Zeit ausgef hrt werden. u

8.2.2

Offene Adressierung

Bei der offenen Adressierung werden alle Elemente in der Hash-Tabelle selbst gespeichert, ohne dass Listen verwendet werden. Wenn die Hash-Tabelle m Pl tze hat, k nnen dann nat rlich auch nur maa o u ximal m Elemente gespeichert werden.

98

KAPITEL 8. HASHING

Die Kollisionsbehandlung erfolgt so, dass f r jeden Schl ssel k auf eine bestimme Weise eine Sonu u dierungssequenz zur Suche nach einer Ersatzadresse angegeben wird, die nacheinander abgearbeitet wird, wenn das Element mit Schl ssel k eingef gt beziehungsweise gesucht werden soll. u u Falls wir ein Element suchen, das nicht in der Tabelle enthalten ist, suchen wir dabei entweder die ganze Tabelle durch oder k nnen abbrechen, sobald wir in der Sondierungssequenz auf einen Eintrag o in der Hash-Tabelle stoen, der leer ist (w re das Element schon gespeichert, so w re es ja an dieser a a Stelle, weil die Sondierungssequenz f r festes k ja jedesmal die gleiche ist). u Wir erweitern also die Hash-Funktion zu einer Funktion h : U {0, 1, . . . , m 1} {0, 1, . . . , m 1} wobei das zweite Argument die Anzahl der schon erfolgten Sondierungen (beginnend bei 0) sein soll. Dabei muss gelten: Permutationsbedingung (h(k, 0), h(k, 1), . . . , h(k, m 1)) ist eine Permutation von (0, 1, . . . , m 1). Folgende Methode f gt ein Element in eine Hash-Tabelle T ein. Dabei sei int h(int, int) die u Hash-Funktion und T die Hash-Tabelle, realsiert als Array von Integer Objekten. boolean hashInsert(Integer[] T, int k) { // returns true, if element is successfully inserted, else false int i = 0; do { int j = h(k,i); if (T[j] == NULL) { T[j] = new Integer(k); return true; } i++; } while (i!=T.length); return false; } Folgender Algorithmus sucht dann den Datensatz mit Schl ssel k: u int hashSearch(Integer[] T, int k) { // returns index of hash table entry, if element is found, else -1 int i = 0; do {

8.2. KOLLISIONSBEHANDLUNG int j = h(k,i); if (T[j].equals(k)) return j; i++; } while (T[j]!=NULL && i!=m); return -1; }

99

Aus einer Hash-Tabelle zu l schen, die offene Adressierung verwendet, ist im Allgemeinen schwierig. o Wir k nnen ein Element nicht einfach l schen, weil dann an dieser Stelle beim Suchen von anderen o o Elementen die Sondierungssequenz abbrechen k nnte und daher andere Elemente nicht mehr gefuno den werden, obwohl sie noch in der Tabelle enthalten sind. Eine m gliche L sung besteht darin, einen Spezialwert GEL OSCHT zu denieren, den wir statt NULL o o in die Hash-Tabelle schreiben, damit die Sondierungssequenz nicht abbricht. Man m sste dann Hashu Insert ein bisschen modizieren, damit dieser Wert dann so behandelt wird, als w re die Tabelle an a dieser Stelle leer. Das Problem ist, dass beim Verwenden von GEL OSCHT die Suchzeit l nger wird und nicht mehr nur a vom Auslastungsfaktor abh ngt. Daher wird, falls gel scht werden muss, meistens Chaining als a o Kollisionsbehandlung gew hlt. a Wir betrachten jetzt drei verschiedene Hash Verfahren, die auf offener Adressierung basieren. Lineare Sondierung / Linear Probing Sei h : U {0, 1, . . . , m 1} eine gew hnliche Hash-Funktion. Dann benutzt man beim Linear Proo bing folgende Hash-Funktion: h(k, i) := h (k) + i mod m Die davon generierte Sondierungssequenz hat folgende Form: h (k), h (k) + 1, h (k) + 2, . . . , m 1, 0, 1, . . . , h (k) 1

Ein Problem beim Linear Probing besteht darin, dass sich leicht Ketten von schon belegten Feldern bilden, weil die Wahrscheinlichkeit, dass ein Element an Stelle k eingef gt wird, wobei vor Stelle k u schon i belegte Felder sind, gleich i+1 ist. Das bezeichnet man als Prim res Clustering. Dadurch steigt a m die Durchschnittszeit f r das Einf gen und Suchen stark an, wenn sich der Auslastungsfaktor der 1 u u n hert. a Das Problem wird besonders drastisch, wenn als Hash-Funktion h dabei die Divisionsmethode verwendet wird und direkt aufeinanderfolgende Schl ssel {k, k + 1, k + 2, . . . } eingef gt werden, weil u u diese dann auch auf Felder gehasht werden, die direkt aufeinanderfolgen.

100

KAPITEL 8. HASHING

h (k)

Abbildung 8.3: Lineare Sondierung Beim Linear Probing gibt es noch eine M glichkeit, das L schen so unterzubringen, dass der Aufo o wand nicht anw chst, wenn man das L schen geringf gig ab ndert (siehe [Knu98]). Beim folgenden a o u a Verfahren ist das aber nicht mehr praktikabel: Quadratische Sondierung / Quadratic Probing Beim Quadratischen Sondieren wird eine Hash-Funktion der Form h(k, i) := h (k) + c1 i + c2 i2 mod m verwendet.
h (k) + 12 h (k) + 20

h (k) + 2 h (k)

h (k) + 6

Abbildung 8.4: Quadratische Sondierung mit c1 = c2 = 1

Dabei ist die Permutationsbedingung kompliziert zu erf llen, denn sie h ngt von c1 , c2 und m ab. Dieu a ses Hashing-Verfahren vermeidet prim res Clustering, f hrt aber zu sogenanntem sekund rem Clusa u a

8.2. KOLLISIONSBEHANDLUNG

101

tering, denn wenn Schl ssel k1 , k2 den gleichen Hash-Wert haben (h(k1 , 0) = h(k2 , 0)), so haben sie u auch die gleiche Sondierungssequenz. Doppelhash / Double Hashing Beim Double-Hashing werden zwei Hash-Funktionen verwendet. Dies ist eine der besten Arten, Kollisionen durch offene Addressierung zu behandeln, weil die vom Double Hashing erzeugten Permutationen viele Charakteristika von zuf lligen Permutationen besitzen. Die Hash-Funktion hat also die a Form h(k, i) = (h1 (k) + ih2 (k)) mod m wobei h1 und h2 einfache Hash-Funktionen sind. Die Verwendung der zweiten Hash-Funktion behebt dabei das Problem des sekund ren Clustering. a Satz 8.2 (Doppelhashing) Die Permutationsbedingung ist beim Doppelhashing genau dann erf llt, u wenn die L nge m der Hash-Tabelle und h2 (k) f r alle k relativ prim sind, also gilt: a u k : ggT (m, h2 (k)) = 1

Beispiel 8.3 Wir machen erst einmal plausibel, dass die Permutationsbedingung nicht erf llt ist wenn u m und h2 (k) nicht relativ prim sind. Dazu geben wir ein Gegenbeispiel explizit an. Seien also h2 (k) = 8, m = 12. Dann ist ggT (h2 (k), m) = 4 =: d. Sei h1 (k) = 1. Die Folge der Adressen lautet dann 1, 9, 5, 1. Es werden dann also nur m = 12 = 3 Adressen in der Hash-Tabelle besucht. d 4 Wir betrachten diesen Sachverhalt nun genauer. Beweis: (von Satz 8.2) Deniere h2 (k) =: w und sei ggT = (m, w) =: d N. Dann gibt es p, q N mit pd = w und qd = m Sei o.B.d.A. h1 (k) = 0. Die Folge der durchlaufenen Adressen hat dann die Form 0, w, 2w, 3w, . . . , q w = q p d = q d p = m p
w m 8.1 8.2

(8.1)

(8.2)

(8.3)

Ein Vielfaches von m modulo m ist aber wieder 0. F r die Zykell nge , also die Anzahl der Schritte, u a bis man zum ersten Mal wieder am Ausgangspunkt angelangt ist, gilt also: q Dann sind zwei F lle zu unterscheiden: a

102 (1) =q

KAPITEL 8. HASHING

Es werden also q Adressen besucht. Da nach Voraussetzung m = q d gilt, folgt d = 1 q = m, also die Aussage des Satzes. (2) <q Nach Spr ngen wird das erste Mal der Ausgangspunkt wieder besucht. Aber nach q Spr ngen wird u u auch der Ausgangspunkt wieder besucht, also muss der Zykel der L nge mehrfach durchlaufen a worden sein und damit ist q ein Vielfaches von . Es gilt also: q = s , s>1 (8.4)

Weil nach Spr ngen der Weite w wieder der Ausgangspunkt erreicht wird, ist also w ein Vielfaches u von m. Es gilt also: w = r m, r1 (8.5) Also gilt pm = qw = s w = srm p = sr Es folgen m = d q = d s und w = d p = d sr Aber weil s > 1, ist d s > d und damit teilt nicht nur d, sondern auch ds schon m und w und ist ein gr erer Teiler als d. Aber nach Voraussetzung war d der gr te gemeinsame Teiler von m und w. o o Widerspruch! Also tritt (2) nicht auf.
8.1 8.2 8.3 8.4 8.5

und

q = s

Analyse unter Gleichverteilungsannahme Die Gleichverteilungsannahme bedeutet hier, dass die n chste Sondierung gleichverteilt unter den m a 1 Adressen eine ausw hlt, also jede mit Wahrscheinlichkeit m . a Satz 8.3 Bei Auslastungsfaktor = 1 gleich 1 . Beispiel 8.4 = Mittel).
1 2 n m

< 1 ist die erwartete Anzahl der Sondierungen beim Einf gen u

1 1

= 2 Sondierungen (im Mittel), = 0, 8

1 1

= 5 Sondierungen (im

8.2. KOLLISIONSBEHANDLUNG Der Beweis beruht auf einer allgemeinen wahrscheinlichkeitstheoretischen Aussage.

103

Satz 8.4 (Urnenmodell) Gegeben seien m Kugeln in einer Urne, davon sind w wei und s schwarz, w + s = m. Es werde aus der Urne gleichverteilt mit Zur cklegen gezogen. Dann ist die erwartete u Anzahl von Ziehungen bis zur Ziehung einer weien Kugel m , also w E(# Ziehungen bis zur ersten weien Kugel) = m . w

Beispiel 8.5 Ein Spezialfall des Urnenmodells ist die mittlere Zahl von W rfeln eines W rfels bis zur u u ersten 6. Dabei entspricht die 6 einer weien Kugel und die Zahlen 1 bis 5 schwarzen Kugeln. Also ist w = 1 und s = 5. Jede Zahl (Kugel) wird mit derselben Wahrscheinlichkeit von 1 gezogen und das 6 Urnenmodell ergibt E(# W rfe, bis das erste mal eine 6 geworfen wird) = u Entsprechend ergibt sich E(# W rfe, bis das erste mal eine 1 oder eine 2 geworfen wird) = u 6 = 3. 2 6 = 6. 1

Bevor wir Satz 8.4 beweisen, rekapituliern wir kurz die Denition des Erwartungswertes f r abz hlbar u a diskrete Zufallsvariable. X bezeichne eine diskrete Zufallsgr e, die die Werte x1 , x2 , . . . , xn annehmen kann, wobei diese Wero te mit den Wahrscheinlichkeiten p1 , p2 , . . . , pn auftreten. Der Erwartungswert (Mittelwert) von X ist deniert als E(X) := xi pi
i=1 n

Im abz hlbar unendlichen Fall ist der Erwartungswert deniert als E(X) = xi pi , falls diese Reihe a
i=1

konvergiert. Im Urnenmodell entspricht zw dem Ziehen einer weien, zs dem Ziehen einer schwarzen Kugel und die Ereignisse treten mit den Wahrscheinlichkeiten p, q ein, wobei p + q = 1. (8.6)

Sei X die Anzahl der Ziehungen, bis zw eintritt. X ist dann eine abz hlbar unendlich diskrete Zufallsa variable mit den Werten x1 = 1, x2 = 2, . . . , xi = i, . . .. Diese Werte treten mit folgenden Wahrscheinlichkeiten auf: x1 = 1 = Folge zw x2 = 2 = Folge zs zw . . . xi = i

mit Wahrscheinlichkeit: p mit Wahrscheinlichkeit: q p

= Folge zs zs . . . zs zw mit Wahrscheinlichkeit: qi1 p =: pi


(i1)mal

104 Zur Kontrolle addieren wir die Wahrscheinlichkeiten noch einmal auf:

KAPITEL 8. HASHING

i=1

pi = qi1 p = p qi = p 1 q = p p = 1
8.6 i=1 i=0

Wir stellen nun die Verbindung zwischen dem Sondieren beim Doppelhash und dem Urnenmodell her. Urnenmodell Ziehen einer weien Kugel Ziehen einer schwarzen Kugel Ziehen mit Zur cklegen u Hashing Hash-Funktion w hlt eine leere Stelle in der Hash-Tabelle a Hash-Funktion w hlt eine besetzte Stelle in der Hash-Tabelle a blindes W hlen eines neuen Platzes a

Dann folgt mit Satz 8.4: E(# Sondierungen) E(# Sondierungen bei Blindwahl) = also der Beweis von Satz 8.3. Wir m ssen daher noch die wahrscheinlichkeitstheoretische Aussage in Satz 8.4 zeigen. u Beweis: (von Satz 8.4) Dazu betrachten wir Folgen von Ziehungen, bis das erste Mal eine weie Kugel gezogen wird: 1. Mal: 2. Mal: 3. Mal: . . . (w) (s, w) (s, s, w) . . .
(i1)mal w Wahrscheinlichkeit : p mit p = m Wahrscheinlichkeit : q p mit q = Wahrscheinlichkeit : q2 p . . . s m

m 1 1 = , n = mn 1 m 1

i-tes Mal: (s, s, . . . , s, w) Wahrscheinlichkeit : qi1 p . . . . . . . . .

Der Erwartungswert f r die Anzahl der Ziehungen ergibt sich dann aus der Denition, indem man u jeden Wert xi = i der Zufallsvariablen X := # Ziehungen bis zur ersten weien Kugel mit der zugeh rigen Wahrscheinlichkeit pi multipliziert und diese Produkte alle aufsummiert. Er ist o also E(X) = 1 p + 2 qp + 3 q2 p + + i qi1 p + . . . =
i=0

i qi1 p
i=1

= p i qi1
:=S

8.2. KOLLISIONSBEHANDLUNG Wir d rfen die Potenzreihe S umordnen, weil sie absolut konvergent ist. Also ist u S = 1 q0 + 2q1 + 3q2 + 4q3 + . . . = q0 + q1 + q2 + q3 + . . . +q1 + q2 + q3 . . . +q2 + q3 + . . . +q3 + . . .

105

( (

q qi ) q2 q )
i=0 i=0 i

i=0

qi )

q3 qi )
i=0

i=0

qi + q qi + q2 qi + . . .
i=0 i=0 i=0

= (1 + q + q2 + q3 + . . . ) qi = = = =

i=0

qi

i=0

qi

1 1 1q 1q 1 1 p p 1 p2

Also gilt f r die erwartete Anzahl E(X) der Ziehungen bis zur ersten weien Kugel u E(X) = =
w p= m

pS 1 p m . w

Korollar 8.2 Die Anzahl der Sondierungen ist im Mittel also gleich gehen Einf gen und Suchen in Hash-Tabellen im Mittel in O(1). u

1 1

und damit konstant. Also

Man k nnte sich nun die Frage stellen, warum wir nicht B ume statt Hashtabellen verwenden und o a auch dort den Aufwand im Mittel betrachten, da sich doch das L schen bei B umen sehr viel einfacher o a gestaltet, und wir den Vorteil der Sortierung gem Inorder-Durchlauf haben. Es gilt jedoch: a

106

KAPITEL 8. HASHING

Satz 8.5 Der mittlere Aufwand f r das Einf gen und Suchen ist bei B umen O(log n). u u a Beweis: Zum Beweis dieses Satzes betrachten wir das Suchen in einem Suchbaum mit n Datens tzen. a Der bestm gliche (weil h henminimale) Baum f r diese Suche ist ein voller Baum, also ein Baum, o o u bei dem alle Schichten bis auf die letzte voll sind (falls n = 2 p 1 mit p N, so ist auch die letzte voll). Betrachte dabei einen Baum T , der auf der untersten Schicht nur ein Element enth lt, so dass a
n1

n=

i=0

2i + 1 = 2h 1 + 1 = 2h

gilt. Wir analysieren das Suchen im Baum T unter der Gleichverteilungsannahme, in diesem Fall also 1 der Annahme, dass jeder Schl ssel mit der gleichen Wahrscheinlichkeit n gesucht wird. u Dann gilt: E(# Anzahl Vergleiche zum Suchen) = = = = Summe der Vergleiche zum Suchen aller Knoten n h #Knoten auf Schicht (h-1) n 1 h 2h1 n 1 n log n n 2 1 log n 2 (log n)

Hash-Tabellen haben also den Vorteil eines konstanten mittleren Aufwandes f r die Basisoperationen u gegen ber Suchb umen. Suchb ume haben dagegen einen Worst Case Aufwand von O(log n) f r die u a a u Basisoperationen und beinhalten per Inorder-Durchlauf eine Sortierung der Datens tze. Esh ngt also a a sehr von der Anwendung ab, ob Hash-Tabellen oder Suchb ume geeigneter sind. a

8.3

Literaturhinweise

Hashtabellen werde in nahezu allen B chern uber Datenstrukturen und Algorithmen behandelt. Die hier gew hlte u a Darstellung lehnt sich an [CLRS01] an.

Kapitel 9

Schaltkreistheorie und Rechnerarchitektur


9.1 Schaltfunktionen und Schaltnetze

Wir wollen nun die logischen Grundlagen der Rechnerarchitektur besprechen. In starker Vereinfachung ist ein Rechner eine Blackbox, die zu einer bestimmen Eingabe ein bestimmte Ausgabe liefert, also abstrakt gesehen:

Blackbox

Es werden n Input-Bits in m Output-Bits transformiert. Ein Rechner entspricht also gewissermaen einer Schaltkreisfunktion F : Bn Bm , B = {0, 1}. Beispiel 9.1 Bei der Addition von zwei k-stelligen Bin rzahlen benutzt man eine Schaltkreisfunktion a F : B2k Bk+1 . Sie bildet also 2k-Bitvektoren auf k + 1-Bitvektoren ab. (yk1 , yk2 , . . . , y1 , y0 , xk1 , xk2 , . . . , x1 , x0 ) (zk , zk1 , . . . , z1 , z0 )
B2k Bk+1 F

Ein Beispiel mit k = 2 ist in Abbildung 9.1 dargestellt.

Beispiel 9.2 Beim Sortieren von 30 16-stelligen Bin rzahlen kann man eine Schaltkreisfunktion S : a B480 B480 verwenden. 107

108

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR Input y0 x1 0 0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 0 0 0 0 0 1 0 1 1 0 1 0 1 1 1 1 Output z2 z1 z0 0 0 0 0 0 1 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 1 0 0 0 1 0 0 1 1 1 0 0 1 0 1 0 1 1 1 0 0 1 0 1 1 1 0 Interpretation y+x = z 0+0=0 0+1=1 0+2=2 0+3=3 1+0=1 1+1=2 1+2=3 1+3=4 2+0=2 2+1=3 2+2=4 2+3=5 3+0=3 3+1=4 3+2=5 3+3=6

y1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

x0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

Abbildung 9.1: Addition von 2 k-stelligen Dualzahlen als Schaltkreisfunktion. Beispiel 9.3 Primzahltest f r 480-stellige Bin rzahlen: p : B480 B1 (einstelliger Output) u a p(x) := 0 x ist keine Primzahl 1 x ist eine Primzahl

Schaltkreisfunktionen mit m = 1 heien Boolesche Funktionen und werden mit kleinen Buchstaben bezeichnet, Schaltkreisfunktionen mit m > 1 werden mit Grobuchstaben bezeichnet. Satz 9.1 Jede Schaltkreisfunktion F : Bn Bm mit m > 1 kann aquivalent durch m Boolesche Funk tionen f1 , f2 , . . . , fm mit fi : Bn B beschrieben werden. Beweis: Als Schaltkreisfunktion hat F die Form F(x1 , x2 , . . . , xm ) = (y1 , y2 , . . . , ym ) Setze yi =: fi (x1 , x2 , . . . , xn ). Dann ist F durch F(x1 , x2 , . . . , xn ) = ( f1 (x1 , x2 , . . . , xn ), f2 (x1 , x2 , . . . , xn ), . . . , fn (x1 , x2 , . . . , xn )) vollst ndig dargestellt. a

9.1. SCHALTFUNKTIONEN UND SCHALTNETZE

109

Zum Verstehen von Schaltkreisfunktionen reicht es also aus, Boolesche Funktionen zu verstehen. Wir werden zeigen, dass jede Boolesche Schaltkreisfunktion bereits durch die Negation, das O DER und das U ND darstellbar ist und es daher ausreicht, diese einfachen Schaltelemente in Hardware bereitzustellen um damit jede Schaltkreisfunktion bauen zu k nnen. o Wir betrachten zun chst Boolesche Funktionen mit wenigen Argumenten: a n=1: x 0 1 f0 (x) 0 0 false f1 (x) 0 1 Identit t a f2 (x) 1 0 Negation f3 (x) 1 1 true

n=2: x 0 0 1 1 y 0 1 0 1 f0 0 0 0 0
FALSE

f1 0 0 0 1
AND

f2 0 0 1 0

f3 0 0 1 1

f4 0 1 0 0

f5 0 1 0 1

f6 0 1 1 0
XOR

f7 0 1 1 1
OR

f8 1 0 0 0
NOR

f9 1 0 0 1
xy

f10 1 0 1 0

f11 1 0 1 1

f12 1 1 0 0

f13 1 1 0 1
xy

f14 1 1 1 0
NAND

f15 1 1 1 1
TRUE

Die wichtigsten f nf dieser Operationen sind u f1 : Konjunktion (, AND) f7 : Disjunktion (, OR) f13 : Implikation (, IMPL) f9 : Aquivalenz (, EQUIV) f6 : Antivalenz, ausschlieende Disjunktion ( , XOR) Auerdem haben eigene Namen f8 : Piercescher Pfeil (, NOR) f14 : Shefferscher Strich (, NAND) Zur Vorbereitung des Darstellungssatzes ben tigen wir erst einige Denitionen. o Zun chst werden wir Boolesche Ausdr cke im Folgenden in arithmetischer Schreibweise schreiben, a u also x y oder xy f r x y, x + y f r x y und x f r x. Damit bringen wir die arithmetischen Eigenu u u schaften von B = {0, 1} zum Ausdruck, wobei 1 + 1 = 1 gilt.

110

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Sei f : Bn B eine Boolesche Funktion mit n Variablen x1 , . . . , xn . Belegungen dieser Variablen mit Werten 0 und 1 entsprechen Bitvektoren der L nge n, also allen 2n Dualzahlen von 0 bis 2n 1. Ist a i1 , . . . , in ein solcher Bitvektor, so heit die Zahl i, deren Dualdarstellung gleich i1 , . . . , in ist, der Index zu i1 , . . . , in . Ein einschl giger Index i von f ist ein Index, f r den f die Dualdarstellung (i1 , . . . , in ) des Index auf a u die 1 abbildet, also f (i1 , . . . , in ) = 1 gilt. Beispiel 9.4 Sei f die durch Tabelle 9.1 denierte Boolesche Funktion. Die einschl gigen Indizes a dieser Funktion sind dann 1, 2 und 5. Index i 0 1 2 3 4 5 6 7 x1 0 0 0 0 1 1 1 1 x2 0 0 1 1 0 0 1 1 x3 0 1 0 1 0 1 0 1 f (x1 , x2 , x3 ) 0 1 1 0 0 1 0 0

Tabelle 9.1: Boolesche Funktion zu Beispiel 9.4 Sei i ein Index von f : Bn B und (i1 , i2 , . . . , in ) seine Dualdarstellung. Dann heit die Boolesche Funktion mi : Bn B mit
i i i mi (x1 , x2 , . . . , xn ) := x11 x22 xnn

und x jj :=
i

x j wenn i j = 1 x j wenn i j = 0

j = 1, . . . , n

der i-te Minterm. Ein Beispiel: f r n = 3 und i = 5 ergibt sich als Dualdarstellung (i1 , i2 , i3 ) von i der u Bitvektor (1, 0, 1) und damit als 5-ter Minterm die Boolesche Funktion m5 (x1 , x2 , x3 ) = x1 x2 x3 . Satz 9.2 (Darstellungssatz fur Boolesche Funktionen) Jede Boolesche Funktion f : Bn B mit f = 0 ist eindeutig darstellbar als Summe der Minterme ihrer einschl gigen Indizes. a Beispiel 9.5 Nach Satz 9.2 gilt f r Beispiel 9.4 u f (x1 , x2 , x3 ) = m1 (x1 , x2 , x3 ) + m2 (x1 , x2 , x3 ) + m5 (x1 , x2 , x3 ) = x1 x2 x3 + x1 x2 x3 + x1 x2 x3

9.1. SCHALTFUNKTIONEN UND SCHALTNETZE Wir uberpr fen das an einigen Eingaben: u (x1 , x2 , x3 ) = (1, 0, 0) f (1, 0, 0) = 100 + 100 + 100 = 010 + 001 + 110 = 0

111

(x1 , x2 , x3 ) = (0, 1, 0) f (0, 1, 0) = 010 + 010 + 010 = 100 + 111 + 000 = 1 Beweis: Aus der Denition von Mintermen folgt mi (x1 , . . . , xn ) = 1 Wir m ssen zeigen, dass u (x1 , . . . , xn ) ist die Dualdarstellung (i1 , . . . , in ) von i. (9.1)

f (x1 , x2 , . . . , xn ) = mi (x1 , x2 , . . . , xn )
iI

gilt, wobei I die Menge der einschl gigen Indizes bezeichnet. Wegen f = 0 ist I = 0 und damit iI mi a / wohldeniert. Wir zeigen die Gleichheit argumentweise f r jeden Bitvektor, indem wir eine Fallunteru scheidung durchf hren. Sei dazu (k1 , . . . , kn ) ein konkreter Bitvektor und k der zugeh rige Index. u o Fall I k ist einschl giger Index von f . a Dann ist f (k1 , . . . , kn ) = 1. Wegen (9.1) ist mk (k1 , . . . , kn ) = 1 und damit wegen k I auch iI mi (k1 , . . . , kn ) = 1. Fall II k ist kein einschl giger Index von f . a Dann ist f (k1 , . . . , kn ) = 0 und wegen (9.1) mi (k1 , . . . , kn ) = 0 f r alle i I. Daher ist auch iI mk (k1 , . . . , kn ) = u 0. Bleibt noch die Eindeutigkeit der Darstellung zu zeigen. Wir nehmen dazu an, dass f auf zwei verschiedene Weisen als Summen von Mintermen darstellbar ist und f hren dies zum Widerspruch. u Seien also f = mi = m j
iI jJ

zwei Darstellungen von f als Summe von Mintermen mit I = J. O.B.d.A. existiere ein k I \ J (sonst vertausche I und J, wegen f = 0 gibt es f r einen der beiden F lle ein solches k). Sei dann (k1 , . . . , kn ) u a die Dualdarstellung von k. Wegen (9.1) gilt dann mk (k1 , . . . , kn ) = 1 und daher iI mi (k1 , . . . , kn ) = 1. Weil aber k nicht in J enthalten ist, folgt aus (9.1), dass m j (k1 , . . . , kn ) = 0 f r alle j J, und daher u

112

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

auch jJ m j (k1 , . . . , kn ) = 0, was ein Widerspruch zu iI mi = jJ m j ist.

Die in Satz 9.2 konstruierte Darstellung nennt man disjunktive Normalform (DNF) einer Booleschen Funktion. Korollar 9.1 Jede Boolesche Funktion ist schon durch die logischen Operationen AND, NOT und darstellbar. Die Von Satz 9.2 nicht erfasste Ausnahme f = 0 kann zum Beispiel durch f = x1 x1 dargestellt werden. Der Darstellungssatz bildet die Grundlage f r den Bau von Schaltkreisen. Dazu m ssen nur die drei u u logischen Operationen AND, NOT und OR als Hardware-Bausteine vorliegen. Dies ist Aufgabe der Elektrotechnik und wir werden darauf nicht weiter eingehen sondern annehmen, dass diese Bausteine zur Verf gung stehen. Wir verwenden daf r die in Abbildung 9.2 dargestellten Symbole. u u
OR

Abbildung 9.2: Inverter, UND-Gatter und ODER-Gatter (von links nach rechts). Als Beispiel f r die Anwendung des Darstellungssatzes betrachten wir die Konstruktion eines Addieru netzes auf Basis der stellenweise Addition von zwei k-stelligen Dualzahlen. Beispiel 9.6 Halbaddierer Ein Halbaddierer hat zwei Inputs und zwei Outputs. Er dient zur Addition der niedrigstwertigsten Bits x0 und y0 von zwei Bin rzahlen x, y und liefert als Output das niedrigstwertigste Bit z0 der a Ergebniszahl z und den Ubertrag u1 f r die 1-te Stelle. Seine Schaltkreisfunktion ist in Tabelle 9.2 u dargestellt. Abbildung 9.3 gibt die Black Box Darstellung des Halbaddierers an. x0 0 0 1 1 y0 0 1 0 1 u1 0 0 0 1 z0 0 1 1 0

Tabelle 9.2: Die Schaltkreisfunktion des Halbaddierers.

9.1. SCHALTFUNKTIONEN UND SCHALTNETZE

113

x0 y0

u1

HA

z0

Abbildung 9.3: Halbaddierer als Black Box Der Halbaddierer besteht aus den Booleschen Funktionen u1 und z0 . Die Funktion u1 hat nur einen einschl gigen Index, n mlich i = 3. Ihre disjunktive Normalform ist also a a u1 (x0 , y0 ) = x0 y0 Die Funktion z0 dagegen hat zwei einschl gige Indizes, n mlich i = 1 und i = 2. Die Minterme dazu a a sind x0 y0 und x0 y0 und damit ergibt sich als disjunktive Normalform z0 (x0 , y0 ) = x0 y0 + x0 y0 Wir k nnen mit diesen Bausteinen den Halbaddierer wie in Abbildung 9.4 dargestellt als Hardware o realisieren. Diese Darstellungsart bezeichnet man als Schaltnetz.

x0 z0

y0

u1

Abbildung 9.4: Halbaddierer als Schaltnetz. Beispiel 9.7 Volladdierer Nun betrachten wir den sogenannten Volladdierer, der zwei Ziffern xi , yi an Position i und den Ubertrag ui von der vorigen Position addiert und als Ergebnis die Ziffer zi der Summe sowie den Ubertrag ui+1 an der n chsten Position ausgibt. Sein Verhalten ist in Tabelle 9.3 angegeben. a F r die beiden Booleschen Funktionen zi und ui+1 ergeben sich dann folgende Darstellungen als DNF: u zi (xi , yi , ui ) = xi yi ui + xi yi ui + xi yi ui + xi yi ui

114

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR xi 0 0 0 0 1 1 1 1 yi 0 0 1 1 0 0 1 1 ui 0 1 0 1 0 1 0 1 zi 0 1 1 0 1 0 0 1 ui+1 0 0 0 1 0 1 1 1

Tabelle 9.3: Die Schaltkreisfunktion des Volladdierers.

ui+1 (xi , yi , ui ) = xi yi ui + xi yi ui + xi yi ui + xi yi ui Wir geben auch hierzu den entsprechenden Schaltkreis an, siehe Abbildung 9.5. Dabei verwenden wir erweiterte Gatter, die eine erh hte Zahl von Eing ngen erlauben. Es ist klar, dass sich ein Gatter mit o a Eing ngen aus 1 Gattern mit je 2 Eing ngen zusammensetzen l sst. a a a

Die Art und Weise, in der der Volladdierer in Abbildung 9.5 konstruiert wird, ist nicht die einzige m gliche Art. Es k nnen durchaus auch verschiedene Varianten von Innenelektronik dasselbe Inputo o Output-Verhalten haben und damit die gleiche Schaltkreisfunktion realisieren. Eine andere M glichkeit, den Volladdierer zu konstruieren, besteht in der Verwendung des schon o konstruierten Halbaddierers als Baustein wie in Abbildung 9.6. Mit Hilfe der nun bekannten Halb- und Volladdierer konstruieren wir jetzt ein sogenanntes asynchrones Paralleladdierwerk. Es heit asynchron, weil der Schaltkreis nicht getaktet wird und es heit Paralleladdierwerk, weil alle Inputbits nicht sequentiell, sondern parallel zur Verf gung stehen. Die u Realisierung als Schaltnetz ist in Abbildung 9.7 angegeben. Die Zeit bis zum Vorliegen des gesamten Ergebnisses h ngt von der Signallaufzeit ab. Diese ist f r a u zk und zk1 sehr lang, da alle Zwischen bertr ge uk1 , uk2 , . . . , u2 , u1 vorher berechnet werden u a m ssen. Dies funktioniert aber nur sequentiell. Bei Bin rzahlen der L nge n haben wir also einen u a a Schaltungsweg der L nge n. F r die Praxis ist das nicht tauglich. a u Eine Beschleunigung ist m glich durch sogenannte Carry-Look-Ahead-Techniken. Das ist eine Zuo satzschaltung, die den Ubertrag (zum Beispiel u5 ) bereits sofort aus y4 , x4 , y3 , x3 , y2 , x2 , y1 , x1 , y0 und x0 berechnet, in diesem Fall also eine Funktion u5 : B10 B1 Dieses Prinzip kann dann rekursiv angewendet werden.

9.2. VEREINFACHUNG VON SCHALTNETZEN

115

yi zi

xi

ui+1 ui

Abbildung 9.5: Schaltnetz des Volladdierers.

9.2

Vereinfachung von Schaltnetzen

Wie wir beim Volladdierer gesehen haben, gibt es verschiedene M glichkeiten, die gleiche Schalto kreisfunktion in Hardware zu realisieren, so dass der dabei entstehende Schaltkreis das gleiche Verhalten zeigt. Die Frage, der wir uns nun zuwenden wollen, ist: Was ist eine gute Art, eine Schaltkreisfunktion in Hardware zu realisieren? Wie k nnen die vorhandenen Freiheitsgrade optimal ausgenutzt o werden? Eine Antwort auf diese Frage ist die Miniaturisierung: Wenn wir nur wenige Gatter verwenden, ben tigen wir weniger Fl che und damit werden die Schaltkreise kleiner und die Signallaufzeiten o a k rzer. u Wir wollen zwei Verfahren betrachten: Verfahren von Karnaugh Verfahren von Quine-McCluskey

116

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

yi

HA
xi z u

ui+1

HA
ui z zi

Abbildung 9.6: Der Volladdierer mit Halbaddierern konstruiert.

yk1

xk1

y2

x2

y1

x1

y0

x0

VA

...

VA

VA

HA

uk1

u3

zk = uk zk1

z2

z1

z0

Abbildung 9.7: Schaltnetz des asynchronen Paralleladdierwerks.

9.2. VEREINFACHUNG VON SCHALTNETZEN Die beiden Verfahren beruhen logisch gesehen auf der Resolution, also der Tatsache, dass x+x = 1 gilt. Beispiel 9.8 f (x1 , x2 , x3 ) = x1 x2 x3 + x1 x2 x3 = (x1 + x1 )x2 x3
1

117

= x2 x3 Die dabei erreichte Vereinfachung veranschaulichen wir durch die Schaltnetze. Ohne die Vereinfachung w rden wir das Schaltnetz in Abbildung 9.8 benutzen, mit Vereinfachung das aus Abbilu dung 9.9.

x1

x2

f (x1 , x2 , x3 )

x3

Abbildung 9.8: Nicht vereinfachtes Schaltnetz.

9.2.1

Das Verfahren von Karnaugh

Das Verfahren von Karnaugh ist nur f r Boolesche Funktionen f : Bn B1 mit wenigen Argumenten u geeignet (n 4), illustriert aber gut das Prinzip der Resolution. F r n = 3 benutzt man das Diagramm aus Abbildung 9.10. Zeilen- beziehungsweise Spaltennachbarn u unterscheiden sich dabei zyklisch um genau ein Bit in ihrer Variablenbelegung. F r n = 4 nutzt man u ein entsprechendes Diagramm mit 4 Spalten und Zeilen. Bei allen einschl gigen Indizes schreibt man dann eine 1 in das Karnaugh-Diagramm. Ein Beispiel a einer Funktion f r n = 4 ist in Abbildung 9.11 angegeben. Zum Beispiel ist 1011 ein einschl giger u a Index und x1 x2 x3 x4 der dazugeh rige Minterm. Sein Nachbar 1111 ist ebenfalls einschl giger Index o a

118

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

x1

x2

f (x1 , x2 , x3 )

x3

Abbildung 9.9: Vereinfachtes Schaltnetz.

x1 x2 x3 0 1 00 01 11 10

Abbildung 9.10: Anordnung der Variablen im Karnaugh Diagramm f r n = 3. u mit Minterm x1 x2 x3 x4 . Offenbar kann auf im Karnaugh-Diagramm benachbarte Einsen wegen der speziellen Anordnung der Variablen Resolution angewendet werden. Hier w re a x1 x2 x3 x4 + x1 x2 x3 x4 = x1 x3 x4 Die Resolution kann dabei sowohl in Spalten als auch in Zeilen angewendet werden. Es w rde zum u Beispiel auch gelten: x1 x2 x3 x4 + x1 x2 x3 x4 = x1 x2 x4 Produktterme d rfen wegen der Regel x + x = x in der Resolution auch mehrfach verwendet werden: u f (x1 , x2 , x3 , x4 ) = x1 x3 x4 + x1 x2 x4 + x1 x2 x4 = x1 x3 x4 + x2 x4 Wir geben noch ein Beispiel f r eine weitreichende mehrfache Resolution an. u g(x1 , x2 , x3 , x4 ) = x1 x2 x3 x4 + x1 x2 x3 x4 + x1 x2 x3 x4 + x1 x2 x3 x4 + x1 x2 x3 x4 = x2 x3 x4 + x2 x3 x4 + x1 x2 x4 + x1 x3 x4 = x2 x4 + x1 x2 x4 + x1 x3 x4

9.2. VEREINFACHUNG VON SCHALTNETZEN

119

x1 x2 x3 x4 00 01 11 10 1 1 1 1 1 00 01 11 10

Abbildung 9.11: Karnaugh Diagramm einer Booleschen Funktion f r n = 4. u Das Karnaugh-Verfahren l sst sich auf gr ere Bl cke erweitern. Betrachten wir zum Beispiel das a o o partielle Karnaugh Diagramm in Abbildung 9.12. Wir k nnen es mit Resolution vereinfachen: o f (x1 , x2 , x3 , x4 ) = x1 x2 x3 x4 + x1 x2 x3 x4 + x1 x2 x3 x4 + x1 x2 x3 x4 = x1 x3 x4 + x1 x3 x4 = x1 x3

x1 x2 x3 x4 00 01 00 1 1 01 1 1

Abbildung 9.12: Bl cke im Karnaugh Diagramm. o Allgemein m ssen die Bl cke als Seitenl ngen 2er-Potenzen haben. Das allgemeine Vorgehen lautet u o a also: W hle m glichst groe Bl cke von 2k 2l , k, l N, die nur aus Einsen bestehen und deren Vereinia o o gung alle Einsen enth lt, und schreibe die zugeh rigen Produktterme auf. Die zugeh rige Boolesche a o o Funktion ergibt sich dann als Summe dieser Produktterme, Die Funktion f in Abbildung 9.11 l sst sich mit einem 44 Block und einem 21 Block uberdecken a und es folgt f (x1 , . . . , x4 ) = x2 x4 + x1 x3 x4 .

120

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Manchmal werden nicht alle Eingabe-Bitvektoren in der Booleschen Funktion ben tigt und man kann o dann frei w hlen, ob man f r diese bitvektoren eine 1 oder eine 0 als Ergebnis haben m chte (die a u o sogenannten dont-cares). Dadurch ist unter Umst nden eine bessere Vereinfachung m glich. Wir a o erl utern dies an einem Beispiel. a Beispiel 9.9 Wir wollen eine Schaltkreisfunktion f r die folgende Funktion konstruieren: u f : {0, 1, 2, . . . , 9} {0, 1}, f (x) := 1 falls x {1, 5, 8, 9} 0 sonst

Wir modellieren diese Funktion als Boolesche Funktion, wobei wir die Eingaben auf nat rliche Weise u durch ihre Bitvektoren Kodieren: Die Schaltkreisfunktion bezeichnen wir ebenfalls mit f , gesucht ist also f : B4 B1 , deren Output nur f r folgende Bitvektoren u Eingabe 0 1 2 3 4 5 6 7 8 9 Bitvektor 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001

Der Rest der m glichen Inputs wird nicht ben tigt. Das zugeh rige Karnaugh-Diagramm ist in Abo o o bildung 9.13 angegeben, wobei das Ergebnis f r nicht ben tigte Inputs mit einem D f r dont-care u o u gekennzeichnet ist. Indem wir alle dont-cares auf 1 setzen, sehen wir, dass bereits folgende Schaltfunktion ausreicht: f (x1 , x2 , x3 , x4 ) = x1 + x3 x4

9.2.2

Das Verfahren von Quine und McCluskey

Eine Boolesche Funktion f : Bn B liegt in disjunktiver Form vor, wenn f als Summe von Termen f = Mi
i=1 k

dargestellt ist. Ein Term Mi ist ein Produkt der Form

xj
j=1

mit x {x, x}.

9.2. VEREINFACHUNG VON SCHALTNETZEN

121

x1 x2 x3 x4 00 01 11 10 1 1 00 01 D D D D D D 11 10 1 1

Abbildung 9.13: Karnaugh Diagramm mit Dont Cares Beispiel 9.10 f : B4 B, liegt in disjunktiver Form vor. Ein Spezialfall der disjunktiven Form ist die sogenannte disjunktive Normalform; bei ihr sind alle Terme Minterme. Zur Bewertung einer Miniaturisierung f hren wir jetzt ein Kostenma ein. Inverter betrachten wir als u kostenlos. Gatter kosten eine Einheit und haben nur zwei Eing nge. a Den Kosten einer Booleschen Funktion in disjunktiver Normalform entspricht die Anzahl der ben tigten o Gatter (mit zwei Eing ngen) zum Bau eines Schaltkreises auf Basis der disjunktiven Normalform. Die a Boolesche Funktion f : B4 B, die wir mit dem erweiterten Verfahren von Karnaugh vereinfacht haben, hat in der Darstellung als Summe von 4 Mintermen Kosten 15 und in der vereinfachten Form f (x1 , x2 , x3 , x4 ) = x1 x3 x4 nur noch Kosten 2. Denition (Vereinfachungsproblem f r Boolesche Funktionen) Bestimme zu einer gegebenen Booleu schen Funktion f : Bn B, die als Tabelle oder in disjunktiver Normalform gegeben ist, eine Darstellung in disjunktiver Form mit minimalen Kosten. Bei der L sung dieses Problems spielt der Begriff des Implikanten eine groe Rolle, den wir nun o einf hren: u Sei f : Bn B eine Boolesche Funktion. Ein Term M heit Implikant von f (in Zeichen (M f ), wenn gilt: M(x1 , x2 , . . . , xn ) = 1 f (x1 , x2 , . . . , xn ) = 1 Ein Implikant M von f heit Primimplikant, falls keine echte Verk rzung (das heit Streichung eines u xi bzw. eines xi ) von M Implikant von f ist. f := x1 + x3 x4

122

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Beispiel 9.11 Wir betrachten die Boolesche Funktion f (x1 , x2 , x3 ) = x1 x2 x3 + x1 x2 x3 + x1 x2 x3 . x1 x2 x3 ist ein Implikant von f , denn aus x1 x2 x3 = 1 folgt f (x1 , x2 , x3 ) = 1. x1 x2 x3 ist jedoch kein Primimplikant von f , denn wegen der Resolution hat f die Darstellung f (x1 , x2 , x3 ) = x1 x3 + x1 x2 und daher ist x1 x3 ein Implikant von f und eine echte Verk rzung von x1 x2 x3 . u x1 x3 ist ein Implikant von f , denn f l sst sich als f (x1 , x2 , x3 ) = x1 x3 + x1 x2 darstellen. Weil die a einzigen m glichen echten Verk rzungen x1 und x3 keine Implikanten von f sind, ist x1 x3 ein Primimo u plikant von f . x1 x2 x3 ist ein Implikant, jedoch kein Primimplikant, denn die echte Verk rzung x1 x2 ist ein Implikant u von f . Satz 9.3 Sei f : Bn B eine Boolesche Funktion ( f 0). Ist d = M1 + M2 + + Mk eine disjunktive Darstellung von f mit minimalen Kosten, so ist jeder Term Mi ein Primimplikant von f . Beweis: Zum Beweis nehmen wir das Gegenteil an, sei also o.B.d.A. M1 kein Primimplikant, aber M1 + M2 + Mk eine kostenminimale Darstellung der Booleschen Funktion f . Weil M1 kein Primimplikant ist, hat M1 eine echte Verk rzung M 1 , die Implikant von f ist. Damit hat f eine Darstellung u d = M 1 + M2 + + Mk Aber dann sind die Kosten von d geringer als die von d, ein Widerspruch zur Annahme.

Das Verfahren von Quine-McCluskey arbeitet wie folgt: 1. Bestimmung aller Primimplikanten von f 2. Auswahl einer kostenminimalen Untermenge, die schon f darstellt F r Schritt 1 k nnen wir Resolution systematisch verwenden, Teil 2 entspricht dem (weiter unten u o behandelten) Uberdeckungsproblem. Zu Schritt 1: Schritt 1 wird wie folgt durchgef hrt: u Teile die Minterme in Gruppen mit gleicher Anzahl von Negationen. Wende Resolution auf benachbarte Gruppen an. Iteriere, bis keine Verk rzung mehr m glich ist. u o Die nicht verk rzbaren Terme sind die Primimplikanten (wird unten bewiesen). u Abbildung 9.14 illustriert diese Vorgehensweise. Zu Schritt 2: Die Auswahl der Primimplikanten erfolgt nach folgenden Kriterien:

9.2. VEREINFACHUNG VON SCHALTNETZEN Gruppen 1 2 3 4 gegeben x1 x2 x3 x4 x1 x2 x3 x4 x1 x2 x3 x4 x 1 x2 x3 x 4 x1 x2 x3 x4 x 1 x2 x 3 x 4 x1 x2 x3 x4 Runde 1 x1 x2 x4 x1 x2 x3 x2 x3 x4 x1 x2 x4 x2 x3 x4 x1 x3 x4

123

x2 x 4

Abbildung 9.14: Ermittlung der Primimplikanten nach Quine-McCluskey. Die Terme in den K sten a sind die Primimplikanten. Bestimme eine Auswahl von Primimplikanten, so dass jeder Minterm durch einen Primimplikanten verk rzt wird (aber nicht unbedingt echt verk rzt). u u Treffe die Auswahl so, dass die Kosten minimal werden. Dazu erstellen wir eine Tabelle, bei der die Spalten den Mintermen und die Zeilen den Primimplikanten entsprechen. Ist dann ein Primimplikant eine Verk rzung eines Minterms, so schreiben wir an die u entsprechende Stelle der Tabelle eine 1, ansonsten eine 0. Abbildung 9.15 gibt ein Beispiel. Gesucht ist nun eine Auswahl von Zeilen, also Primimplikanten, so dass die zugeh rigen Einsen alle Spalten, o also Minterme, uberdecken. Dies ist ein als algorithmisch schwierig bekanntes allgemeines Problem, das sogenannte Uberdeckungsproblem. Doch dazu sp ter mehr. a x1 x2 x3 x4 1 x1 x2 x3 x4 1 1 1 x1 x2 x3 x4 x1 x2 x3 x4 x1 x2 x3 x4 1 1 1 1 1 x 1 x2 x 3 x 4 x

x1 x 2 x3 x4 x1 x2 x3 x1 x3 x4 x2 x 4

Abbildung 9.15: Die Tabelle f r das Uberdeckungsproblem zum Beispiel aus Abbildung 9.14. u In Abbildung 9.15 gibt es nur eine m gliche Auswahl von Primimplikanten (n mlich alle). Im Allo a gemeinen sind jedoch mehrere Auswahlen von Mengen von Primimplikanten m glich. Ein Beispiel o dazu im Karnaugh-Diagramm ist in Abbildung 9.16 angegeben. Wir zeigen nun, dass die fortgesetzte Resolution in Schritt 1 tats chlich alle Primimplikanten ergibt. a Satz 9.4 Seien M1 , M2 , . . . , Mk die Terme, die durch fortgesetzte Resolution, bis keine echte Verk rzung u mehr m glich ist, aus der disjunktiven Normalform von f entstehen (dabei ist Mi = M j f r alle i, j). o u Dann sind M1 , . . . , Mk genau die Primimplikanten von f . Beweis: Wir m ssen zeigen: u

124

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Abbildung 9.16: Ein Uberdeckungsproblem mit zwei verschiedenen L sungen (aber gleichen Kosten). o 1. Jeder Term Mi ist Primimplikant von f . 2. Es gibt keine weiteren Primimplikanten von f . Zu 1: Weil jedes Mi durch Resolution entsteht, ist jedes Mi Implikant von f . Wir nehmen nun an, dass Mi ein Implikant, aber kein Primimplikant ist. Dann gibt es eine echte Verk rzung Mi von Mi . u Diese ist gekennzeichnet durch den Wegfall eines x j beziehungsweise eines x j . Weil Mi Implikant war, ist Mi ebenfalls Implikant. Betrachten wir nun folgenden Fall: Das x j beziehungsweise x j , das in Mi , aber nicht in Mi vorkommt, sei so mit einem Wert belegt, dass Mi = 0 wird. Belege alle anderen Variablen mit Werten so, dass Mi = 1 wird und gleichzeitig alle anderen Terme M j = 0 werden. (Das ist m glich, da sich die anderen Terme nach Voraussetzung von Mi unterscheiden). Sei y = (y1 , y2 , . . . , yn ) o die entstehende Belegung der xi mit 0 bzw. 1. Dann gilt Mi (y) = 1, und es folgt f (y) = M (y) = 0, = 1, . . . , k,

Mi (y) = 0.
=1

Aber nach Voraussetzung war Mi Implikant von f , so dass aus Mi (y) = 1 auch f (y) = 1 folgt. Dies ist ein Widerspruch. Zu 2: Wir nehmen also an, dass noch ein weiterer Primimplikant M von f existiert. Wir betrachten in der disjunktiven Normalform alle Minterme mi , f r die M eine Verk rzung ist. Sei I die Indexmenge u u dieser i. Dann k nnen wir aus der Summe uber alle diese mi , i I den Term M ausklammern: o

mi = M( mi )
iI iI

9.2. VEREINFACHUNG VON SCHALTNETZEN

125

Falls nun iI mi = 1 gilt, so ist nichts mehr zu zeigen, denn dann entsteht M durch Resolution und wir sind fertig, denn die Terme, die durch Resolution entstehen, sind genau die Terme, die wir im Verfahren von Quine-McCluskey erhalten. Sei also iI mi = 1. Dann gibt es eine Belegung y der Variablen in iI mi , die den Wert 0 ergibt. Wir k nnen die restlichen o Variablen so belegen, dass M(y) = 1 gilt und dass mi (y) = 0 f r alle i I, i einschl giger Index von f , u a erf llt ist. Es folgt f (y) = 0, aber M(y) = 1. Dies ist ein Widerspruch dazu, dass M ein Implikant von u f ist.

9.2.3

Das Uberdeckungsproblem

Das Uberdeckungsproblem ist von ubergeordneter Bedeutung und tritt an vielen Stellen in der angewandten Mathematik auf. Zum Beispiel bei der Zuordnung von Mitarbeitern i (Zeilen der Tabelle) zu Aufgaben j (Spalten der Tabelle), wobei eine 1 bedeutet, dass der Mitarbeiter i die Aufgabe j bearbeiten kann. Zus tzlich kann man eine Gewichtung wi j einf hren, die angibt, wie gut Mitarbeiter i a u Aufgabe j bearbeiten kann. Das Uberdeckungsproblem besteht in der ungewichteten Version darin, eine Auswahl von Mitarbeitern zu nden, so dass alle Aufgaben bearbeitet werden. In der gewichteten Version m chte man zus tzlich die Qualit t maximieren, also die Summe aller Gewichte wi j der einer o a a Aufgabe zugeordneten Mitarbeiter m glichst gro machen. o Das Uberdeckungsproblem ist fundamental schwerer als alle Probleme, die wir bisher in der CoMa behandelt haben. Alle bisherigen Aufgaben waren efzient (lies: in polynomialer Zeit) l sbar. Zum o Beispiel:

Optimaler Pr xcode a K rzeste Wege u Optimaler statischer Suchbaum Sortieren . . .

O(n log n) O(n2 ) O(n4 ) O(n3 ) O(n log n) O(n2 ) . . .

Die Klasse der Probleme, f r die ein solcher polynomialer Algorithmus existiert, bezeichnet man mit u P. F r das Uberdeckungsproblem ist offen, ob es einen solchen Algorithmus gibt. Nach der Klassizieu rung der Schwierigkeit von Problemen geh rt das Uberdeckungsproblem zu der Klasse NP besonders o schwieriger Probleme (das wird in den Vorlesungen ADM I oder Efziente Algorithmen pr zisiert). a Abbildung 9.17 gibt eine Ubersicht uber einige Komplexit tsklassen. a Es ist ein offenes Problem, ob P = NP oder P = NP gilt. W rde man einen efzienten Algorithmus u f r das Uberdeckungsproblem nden, w rde das P = NP implizieren. F r die L sung dieses Problems u u u o hat das Clay Institute of Mathematics 1.000.000$ ausgeschrieben.

126

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Universum aller Probleme Halteproblem

berechenbare Probleme NP

exponentielle Laufzeit efzient l sbar (zum Beispiel K rzeste-Wege-Problem) o u

Abbildung 9.17: Komplexit tsklassen. a

9.3

Schaltungen mit Delays

Wir haben bisher nur azyklische Schaltwerke betrachtet und haben keine R ckkopplung zugelassen. u Das schr nkt die Konstruktionsm glichkeiten aber sehr ein und wir m chten jetzt dazu ubergehen, in a o o unseren Schaltungen bereits berechnete Ergebnisse erneut als Input zu verwenden. Beispiel 9.12 (Ringz hler) (siehe Ubung) a F(xn1 , xn2 , . . . , x0 ) = (
Bin rdarstellung von x a

yn1 , yn2 , . . . , y0

Bin rdarstellung von x+1 mod z a

Einen Ringz hler benutzt man dazu, Zeitschritte im Rechner zu z hlen. Die herk mmlich Realisierung a a o als Schaltfunktion ist zwar m glich, aber nicht sinnvoll, weil der Ringz hler die Zeitschritte ja zyklisch o a zu z hlen hat. Daf r ist es offensichtlich n tig, die Ausgabe des Z hlers als neue Eingabe aufzufassen. a u o a Eine solche R ckkopplung ist jedoch nicht so ohne Weiteres m glich und f hrt zu undeniertem u o u Outputverhalten, wie die Flimmerschaltung in Abbildung 9.18 zeigt. Zur Realisierung der R ckkopplung ben tigt man ein neues Schaltelement, das sogenannte Delay. u o Dieses ist in der Lage, ein Bit zu speichern und gem eines aueren, getakteten Signals auszugeben. a Es ist schematisch in Abbildung 9.19 dargestellt. Bei einem Delay werden zwei Phasen unterschieden:

9.3. SCHALTUNGEN MIT DELAYS

127

0/1

1/0
Abbildung 9.18: Flimmerschaltung. Der Output immert zwischen 0 und 1.

xi

yi Fan-Out

Takt
Abbildung 9.19: Delay mit Fanout. Arbeitsphase: In der Rechenphase wird der Inhalt von S als Signal yi abgegeben und das Signal xi in V abgelegt. Setzphase: In der Setzphase wird durch einen Taktgeber die Sperre zwischen V und S aufgehoben und dadurch der Inhalt von S durch den Inhalt von V ersetzt. Die Setzphase erfolgt zentral gesteuert durch Signalleitungen f r alle Delays gleichzeitig; die Zeit zwischen zwei Signalen u wird die Taktzeit genannt. Fan-Out bedeutet dabei, dass der Ausgang an mehrere Schaltelemente gleichzeitig weitergereicht wird. Delays sind auf elektronischer Ebene durch sogenannte Latches oder Flipops realisierbar, uns interessiert aber nur die logische Seite. Wir k nnen die Flimmerschaltung nun so modizieren, dass sie abwechselnd 0 und 1 pro Takt ausgibt, o siehe Abbildung 9.20. Ein Delay kann so aber nur ein Bit speichern. Begrifich fasst man mehrere Delays, genauer 2erPotenzen von Delays, zu einem sogenannten Register zusammen, siehe Abblildung 9.21. Inhalte von Registern werden als Oktal- oder Hexadezimalziffern dargestellt. Der Inhalt entspricht dabei dem Wort im Register. Operationen im Rechner erfordern i. A. mehrere Takte. Um den richtigen Takt f r das Ablesen des u Ergebnisses einer mehrtaktigen Operation festzustellen, wird ein Ringz hler benutzt. a

128

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

0 ...

0/1
Abbildung 9.20: Flimmerschaltung mit Delay.

...

...

...

...

Wortl nge a

Abbildung 9.21: Register.

9.3.1

Addierwerke

Wir haben schon Addierwerke kennengelernt, die in der Lage sind, f r Bin rzahlen einer festen Stelu a lenzahl n zu addieren. Dabei haben wir nicht ber cksichtigt, woher die Summanden kommen und u wohin das Ergebnis dann geht. Darum wollen wir uns jetzt k mmern. Dazu treffen wir folgende Veru einbarung: Ein Addierwerk soll zwei Register enthalten, einen Akkumulator, der am Beginn den einen Summanden enth lt, und einen Puffer, der den anderen Summanden enth lt. Das Ergebnis der Recha a nung soll dann wieder im Akkumulator stehen. Wir kennen schon das asynchrone (ohne Takt arbeitende) Paralleladdierwerk, das nach der gerade getroffenen Vereinbarung die in Abbildung 9.22 angegebene Form hat. Wir erweitern dieses Addierwerk jetzt mit einem Delay, das den Ubertrag aufnimmt (bei Addition von zwei n-stelligen Bin rzahlen kann eine n + 1-stellige Bin rzahl entstehen). Unser synchrones, also a a getaktetes, 4-Bit-Addierwerk hat die in Abbildung 9.23 angegebene Form. Die Schaltung zeigt, dass einige Schaltelemente mehrere Inputs haben (Fan-In), die je nach Takt Input von auen oder Zwischenergebnis einer internen Rechnung sein k nnen. Wir gehen sp ter darauf ein, wie dieses Problem o a gel st wird. o Ein Nachteil dieses Synchronaddierwerks besteht darin, dass die Signallaufzeiten vergleichsweise lang sind, da die Volladdierer auf den Ubertrag der vorigen Stufe warten m ssen. Wir m ssen also entu u weder lange Taktzeiten verwenden oder mehrere Takte lang auf das Ergebnis warten, also eine Zusatzschaltung mit Ringz hler verwenden. a

9.3. SCHALTUNGEN MIT DELAYS


Akkumulator (1. Input) ... (in Register)

129

Addierwerk

... Puffer (2. Input)

(in Register)

Abbildung 9.22: Asynchrones Paralleladdierwerk.

x3

x2

x1

x0

Akkumulator

VA Ubertrag an Stelle n + 1 y3

VA

VA

HA

y2

y1

y0

Puffer

Abbildung 9.23: Synchrones Paralleladdierwerk. Abhilfe schafft ein serielles Addierwerk, das wir jetzt betrachten wollen (siehe Abbildung 9.24. Dabei sind Akkumulator und Puffer Schieberegister. Wir verwenden Rechts-Verschieben, bei jedem Schiebevorgang wird die am weitesten linke Stelle frei und der Inhalt des am weitesten rechts stehenden Delays kommt nach dem Verschieben im Register nicht mehr vor. Das serielle Addierwerk ist leicht auf mehr Stellen erweiterbar, man ben tigt lediglich gr ere Regiso o ter, aber keine zus tzliche Logik, die beim Paralleladdierwerk erforderlich w re. Die Signallaufzeit ist a a jetzt kurz, aber das serielle Addierwerk liefert das Ergebnis erst nach n Schritten. Nun stellt sich nat rlich die Frage, welches von den beiden Addierwerken in der Praxis eingesetzt u wird. Die Antwort darauf lautet: Es wird keines der beiden Addierwerke eingesetzt. Man kann n mlich a die Vorteile der beiden Addierwerke verkn pfen. Dazu kombiniert man die beiden Addierwerke zu eiu nem Addierwerk, dessen Schrittzahl von den Summanden abh ngt zum sogenannten von-Neumanna Addierwerk. Der logischen Aufbau dieses Addierwerkes ist in Abbildung 9.25 dargestellt. Der Witz beim von Neumann Addierwerk besteht darin, Ubertr ge erst in sp teren Runden zu vera a arbeiten. Im Puffer sind dabei Ubertr ge, im Akkumulator das Zwischenergebnis gespeichert. Das a Delay S gibt an, ob die Rechnung beendet ist. Sie ist genau dann beendet, wenn keine Ubertr ge mehr a

130

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR


A3 x3 A2 x3 A1 x3 A0 x3

VA

y3 P3

y2 P3

y1 P3

y0 P3

Abbildung 9.24: Synchrones serielles Addierwerk. vorhanden sind. Daher h ngt die Anzahl der Runden von den entstehenden Ubertr gen und damit vom a a Input ab. Tabelle 9.26 zeigt ein Beispiel. Bzgl. der Anzahl der Runden gilt folgender Satz: Satz 9.5 Die Anzahl der Runden bei bei der Addition von zwei n-stelligen Dualzahlen mit dem vonNeumann-Addierwerk betr gt im Mittel log n . a Der Grund daf r ist, dass sich die erwartete Anzahl von Einsen in der Ubertr gen pro Runde halbiert. u a Wir geben keinen genauen Beweis f r diesen Sachverhalt an, sondern wenden uns dem noch nicht u gekl rten Problem des Fan-In zu. a

9.3.2

Das Fan-In-Problem

Ein Delay kann also mehrere Eing nge haben, von denen taktabh ngig aber nur einer ber cksichtigt a a u werden soll. Abbildung 9.27 zeigt den Standardfall. Abh ngig vom Takt soll entweder I (neuer Input) a oder R (Rechenergebnis) die Eingabe f r das Delay sein. u Wir uberlegen uns eine Boolesche Funktion, die das Problem l st. Eine solche Boolesche Funktion o muss folgendes Verhalten zeigen: f (S, I, R) := I falls S = 0 R falls S = 1

Die Boolesche Variable S unterscheidet dabei, ob der Input von I oder von R kommt. Die Wertetabelle dieser Booleschen Funktion ist in Abbildung 9.28 dargestellt. Eine Realisierung als Schaltznetz zeigt Abbildung 9.29.

9.4. PLAS UND DAS PRINZIP DER MIKROPROGRAMMIERUNG

131

A3 U HA P3

A2

A1

A0 Akkumulator

HA P2

HA P1

HA P0 Puffer

Abbildung 9.25: von Neumann Addierwerk.

9.4

PLAs und das Prinzip der Mikroprogrammierung

Als Programmierbares Logisches Array (PLA) bezeichnet man einen standardisierten Baustein zur Realisierung von Schaltfunktionen (auf Basis von Booleschen Funktionen in disjunktiver Form). Die Schaltfunktion kann durch Mikroprogrammierung eingestellt beziehungsweise ver ndert werden. a Wir zeigen nun, wie sich solche Bausteine mit den bisherigen Uberlegungen realisieren lassen.

9.4.1

Aufbau eines PLAs

Ein PLA hat prinzipiell die in Abbildung 9.30 angegebene Form. Auf jedem Knotenpunkt kann genau eins von vier verschiedenen Schaltelementen benutzt werden. Dies sind in Abbildung 9.31 dargestellt. Typischerweise haben PLAs zwei Ebenen, die UND- und die ODER-Ebene. In der UND-Ebene werden Terme f r erzeugt und anschlieend in der ODER-Ebene zu disjunktiven Formen addiert. Dies u ist schematisch in Abblildung 9.32 illustriert. Wir erl utern die Realsierung einer Schaltfunktion mit a einem PLA exemplarisch an der Schaltfunktion F(x, y, z) = (yz + xyz, xz + xyz). Die entsprechende Belegung des PLA mit Bausteinen ist in Abbildung 9.33 angegeben. Kommen wir nun zur Realisierung der PLA-Schaltelemente. Die vier Bausteine lassen sich direkt aus

132

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR Summand I Summand II Ergebnis ohne Ubertr ge a Ubertr ge a Ergebnis ohne Ubertr ge a Ubertr ge a Ergebnis ohne Ubertr ge a Ubertr ge a Ergebnis 1 1 0 0 0 1 1 0 1 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0

1 1 0 1 0 1

Abbildung 9.26: Eine Rechnung im von Neumann Addierwerk.


R

Delay

Abbildung 9.27: Fan-In bei einem Delay. ihrer disjunktiven Normalform als Schaltkreise realisieren. Diese sind in Abbildung 9.34 angegeben. Auf einem PLA mit n Inputs, m Outputs und k Spalten k nnen also alle Schaltfunktionen realisiert o werden, die h chstens n Inputs haben, h chstens m Outputs und insgesamt h chstens k Terme (gegeo o o benenfalls mit Quine-McCluskey reduzieren). Es gibt eine Kurzschreibweise f r PLAs, in der nur die u Typen 1, 2, 3, 4 der Bausteine notiert werden, vgl. Abbildung 9.35 f r das letzte Beispiel. u Es gibt nat rlich i. A. verschiedene M glichkeiten zur Realisierung einer Schaltkreisfunktion auf dem u o einem PLA. F r die bereits betrachtete Schaltkreisfunktion u F(x, y, z) = (yx + xyz, xz + xyz)
u v

k nnen wir die Komponenten u und v auch folgendermaen ausdr cken o u u = yz + xyz = (x + x)yz + xyz = xyz + xyz + xyz v = xz + xyz = x(y + y)z + xyz = xyz + xyz + xyz, und damit das PLA alternative wie in Abbildung 9.36 belegen. Dies realisiert die gleiche Schaltfunktion in nicht optimierter disjunktiver Normalform auf einem PLA derselben Gr e. Wenn also das PLA o gro genug ist, muss man die disjunktive Form nicht optimieren.

9.4. PLAS UND DAS PRINZIP DER MIKROPROGRAMMIERUNG S 0 0 0 0 1 1 1 1 I 0 0 1 1 0 0 1 1 R 0 1 0 1 0 1 0 1 Output 0 0 1 1 0 1 0 1

133

Abbildung 9.28: Fan-In Schaltfunktion.

Delay 0 0

I R

1 0 0

Abbildung 9.29: Fan-In Schaltkreis.

9.4.2

Zur Programmierung von PLAs

In der bisherigen Betrachtung haben wir nur logische Arrays verwendet, aber noch nicht ihre Programmierm glichkeiten ber cksichtigt. Diese ergibt sich dadurch, dass man den Bausteintyp durch o u eine zus tzliche Steuerung ver ndern kann. a a Dazu bringt man an jedem Baustein eines PLAs Steuerleitungen an, die bestimmen, ob dieser Baustein gerade Typ 0, 1, 2 oder 3 realisiert. Da 4 verschiedene Zust nde angesteuert werden sollen, ben tigt a o man daf r zwei Steuerleitungen. Bezeichnet man die Inputs dieser Steuerleitungen mit s und t, so kann u das Verhalten eines Bausteins durch folgende Tabelle beschrieben werden. Bausteintyp 0 1 2 3 s 0 0 1 1 t 0 1 0 1 u y x+y y y v x x xy xy

Hieraus berechnet man sofort u = y + stx, v = sx + stxy + stxy und erh lt die Schaltung aus Abbila dung 9.37. Diese Bauweise erlaubt also die Steuerung des Bausteintyps uber die Steuerleitungen s und t.

134

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

auf jedem Gitterpunkt 4 Typen von Schaltelementen

Abbildung 9.30: Schema eines PLA.

x y
0

x y y
1

x x+y y
2

x y y
3

x
1. Identer

x
2. Addierer

xy
3. Multiplizierer

xy
4. Negatmultiplizierer

Abbildung 9.31: Die vier Schaltelemente eines PLA. Auf dem gesamten PLA ben tigt man 2 Signale pro Baustein, also insgesamt einen Vektor mit 2(n + o m) k Bits zur Steuerung aller Bausteine des PLA. Dieser Vektor ist sehr lang; zur Vereinfachung werden verschiedene Steuervektoren daher uber ein ROM (read-only memory) verwaltet. Das ROM selbst wird wieder durch ein PLA realisiert, dessen Bauweise in Abbildung 9.38 angegeben ist. Ein solches ROM hat in der UND-Ebene die ublichen PLA-Bausteine, in der ODER-Ebene stehen pro Spalte die Werte eines Signalvektors zur Steuerung eines anderen PLAs. Die UND-Ebene des ROMs dient zur Ansteuerung einer ganz bestimmen Spalte, woraufhin der Inhalt der Spalte der ODER-Ebene ausgelesen wird (also der Inhalt der Steuersignale). Dazu werden in der UND-Ebene in Spalte i genau die Bausteine benutzt, so dass an die ODER-Ebene eine 1 genau dann weitergegeben wird, wenn als Input die Bin rdarstellung von i vorliegt. In Spalte i der UND-Ebene stehen also die Bausteine a b1 , b2 , . . . , b mit bj = 2 wenn Bitdarstellung von i an Stelle j den Wert 1 hat 3 wenn Bitdarstellung von i an Stelle j den Wert 0 hat

9.5. LITERATURHINWEISE

135

Termerzeugung UND-Ebene

Addition von Termen ODER-Ebene

Abbildung 9.32: UND/ODER Ebenen eines PLA. Die Eingabe der Bitfolge einer Addresse bewirkt also, dass genau die zugeh rige Spalte der ODERo Ebene am Output erzeugt wird und keine andere. Ein konkretes Beispiel ist in Abbildung 9.39 angegeben. Abbildung 9.40 zeigt diesen Vorgang schematisch. Das Einlesen einer Adresse bewirkt die Ausgabe genau eines Vektors von Steuersignalen an ein PLA, das dann entsprechend eine Schaltfunktion realisiert. Diese Idee kann noch erweitert werden, indem Steuersignale nicht aus einem ROM abgerufen werden, sondern (teilweise) direkt aus Schaltkreisen heraus erzeugt werden. Dadurch kann der Rechner also das Verhalten seiner PLAs und damit sein eigenes Verhalten auf der Hardware-Ebene andern! Diese M glichkeit bezeichnet man als Mikroprogrammierung. Sie ist schematisch in Abbildung 9.41 o dargestellt.

9.5

Literaturhinweise

Dieses Kapitel folgt der Darstellung in [OV03].

136

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

1 x 0 1 y 3 y z 2 yz 1 ODEREbene 0 yz 2 2 2

1 2

1 2

3 xyz

xyz 1 0

u = yz + xyz

v = xz + xyz

Abbildung 9.33: PLA Belegung f r die Schaltfunktion F(x, y, z) = (yz + xyz, xz + xyz). u

x y x y y xy
1. Identer 2. Addierer 3. Multiplizierer

x y y y

xy
4. Negatmultiplizierer

Abbildung 9.34: Schaltkreise f r die Bausteine eines PLA. u

9.5. LITERATURHINWEISE

137

0 3 2 1 0

2 2 2 1 0

2 0 2 0 1

2 2 3 0 1

Abbildung 9.35: Kurzschreibweise f r den PLA zur Schaltkreisfunktion F(x, y, z) = (yz + xyz, xz + u xyz).

x y z

2 3 2

3 3 2

2 2 2

2 2 3

xyz xyz xyz xyz 1 1 1 0 1 0 1 1

Abbildung 9.36: Alternative PLA Belegung zur Schaltkreisfunktion F(x, y, z) = (yz + xyz, xz + xyz).

s y

x t u

v u = y + stx v = sx + stxy + stxy

Abbildung 9.37: PLA Baustein mit Steuerleitungen.

138

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

log L Zeichen Addresse der Spalte U ND -E BENE f r Bitkodierung der Spalten u

O DER -E BENE L

jede Spalte des ROM entspricht einem Vektor von Steuersignalen zur Erzeugung einer ganz bestimmten Schaltfunktion auf dem Ausgangs-PLA

Abbildung 9.38: Funktionsweise eines ROM als PLA.

Baustein-Typen 1 0 1 3 3 3 0 3 3 2 0 3 2 3 0 3 2 2 0 2 3 3 0 2 3 2 1 3 3 3 3 Addressen 0 1 2 3 4 5 6 7 2 2 3 0 2 2 2 0

ein Vektor von Steuersignalen an Addresse 5

Abbildung 9.39: Beispiel f r ein ROM. Die Adresse (1, 0, 1) wird in der UND-Ebene dekodiert und u der Inhalt (der Steuervektor (3, 3, 3)) in der ODER-Ebene ausgegeben.

9.5. LITERATURHINWEISE

139

1 0 1 0 ... ... ... b1 b2 . . . b

log L Zeichen

L Addressen/Vektoren

Steuersignal - Vektor an Addresse

PLA Steuersignale

Abbildung 9.40: Beispiel f r ein ROM. Die Adresse (1, 0, 1) wird in der UND-Ebene dekodiert und u der Inhalt (der Steuervektor (3, 3, 3)) in der ODER-Ebene ausgegeben.
Worte, gewisse Steuerleitungen

x Delays PLA

ein Teil des Outputs des PLAs ist Teil der Steuersignale f r n chsten Takt u a

Abbildung 9.41: Das Prinzip der Mikroprogrammierung.

140

KAPITEL 9. SCHALTKREISTHEORIE UND RECHNERARCHITEKTUR

Literaturverzeichnis
[CLRS01] Thomas H. Cormen, Charles E. Leiserson, Ronald R. Rivest, and Clifford Stein. Introduction to Algorithms. The MIT Press, Cambridge, MA, second edition, 2001. 1.3, 2.3, 3.5, 4.2, 5.4, 6.4, 7.3, 8.3 [HU79] [Knu71] [Knu98] [OV03] [OW02] [SS02] John E. Hopcroft and Jeffrey D. Ullman. Introduction to Automata Theory, Languages, and Computation. Addison-Wesley, Reading, NY, 1979. 1.3 Donald E. Knuth. Optimum binary search trees. Acta Inform., 1:1425, 1971. 6.4 Donald. E. Knuth. The Art of Computer Programming, volume 3 Sorting and Searching. Addison-Wesley, Reading, NY, second edition, 1998. 2.3, 4.2, 8.1.2, 8.2.2 Walter Oberschelp and Gottfried Vossen. Rechneraufbau und Rechnerstrukturen. Oldenburg Verlag, M nchen, 9 edition, 2003. 9.5 u Thomas Ottmann and Peter Widmayer. Algorithmen und Datenstrukturen. Spektrum Akademischer Verlag, 2002. 4. Auage. 2.3, 4.2 Gunter Saake and Kai-Uwe Sattler. Algorithmen und Datenstrukturen: eine Einf rung mit u Java. dpunkt.verlag, Heidelberg, 2002. 2.3, 4.2

141

Index
Aquivalenz, 111 Uberdeckungsproblem, 127 Addierer, 138 Addierwerk asynchrones Parallel-, 131 serielles, 132 synchrones Parallel-, 131 Von-Neumann-, 133 AND, 111 Antivalenz, 111 Auslastungsfaktor, 99 AVL-Baum, 55 B-Baum, 85 Balance, 55 Basisoperationen in AVL-B umen, 63 a in B-B umen, 88 a B ume, 15 a bin re, 16 a Traversierung von, 22 Block, 85 Blockcode, 29 Boolesche Funktion, 110 Bucketsort, 1 einfaches, 2 Chaining, 98 Code, 29 adaptiver, 40 dynamischer, 40 statischer, 40 Codierung, 29 zeichenweise, 40 Delay, 129 Disjunktion, 111 disjunktive Normalform, 114 Divisionsmethode, 97 DNF, 114 Doppelrotation, 59 Double Hashing, 102 dynamische Optimierung, 82 echte Verk rzung, 123 u Einf gen eines Knotens u in AVL-B umen, 64 a in B-B umen, 88 a Entropie, 43 Fan-In, 134 Flimmerschaltung, 129 Gleichverteilungsannahme, 99 Halbaddierer, 114 Hash-Funktion, 96 Hashing, 95 Double, 102 H ugkeitsverteilung, 73 a Huffman Code, 33 adaptiver, 41 Identer, 138 Implikant, 123 Prim-, 123 Implikation, 111 Index, 111 einschl giger, 112 a Inorder-Durchlauf, 22 Iterator, 25 142

INDEX Karnaugh-Verfahren, 119 Kollision, 95 Kollisionsbehandlung, 95 Konjunktion, 111 Lempel-Ziv Code, 41 L schen eines Knotens o in AVL-B umen, 67 a in B-B umen, 90 a Minterm, 112 Multiplikationsmethode, 97 Multiplizierer, 138 Negatmultiplizierer, 138 normierte H ugkeit, 43 a Offene Adressierung, 100 Open Addressing, 100 Optimale Substruktur, 38, 73 Optimalit t, 37, 72 a asymptotische, 44 OR, 111 Paralleladdierwerk asynchrones, 131 synchrones, 131 Permutationsbedingung, 100 Pierce-Pfeil, 111 PLA, 135 Postorder-Durchlauf, 22 Pr xcode, 31 a Preorder-Durchlauf, 22 Primimplikant, 123 Priority Queue, 25 Probing linear, 101 quadratic, 102 Quine-McCluskey-Verfahren, 123 Redundanz, 43 Register, 130 Resolution, 118 Ringz hler, 129 a Rotation, 49, 59 run length code, 41 Schaltkreisfunktion, 109 Schaltkreistheorie, 109 Schaltnetz, 116 Sheffer-Strich, 111 Sondierung lineare, 101 quadratische, 102 Splitten eines Knoten, 88 Suchbaum, 45 -eigenschaft, 46 Einf gen im, 46 u L schen im, 47 o optimaler statischer, 71 Suchen im, 46 Suchbaumeigenschaft, 46 Suchen eines Knotens in AVL-B umen, 64 a in B-Bauen, 88 Urnenmodell, 105 variable length code, 30 Verfahren von Karnaugh, 119 Quine-McCluskey, 123 verlustfrei, 29, 40 Volladdierer, 116 XOR, 111 Zugriffsh ugkeit, 72 a Zugriffszeit, 73

143

Das könnte Ihnen auch gefallen