Algorithmik 1 Prof. Dr. Michael Philippsen / Prof. Dr. Herbert Stoyan Friedrich-Alexander-Universität Erlangen-Nürnberg Informatik 2/8 Programmiersysteme / Künstliche Intelligenz Organisatorisches Statistik der Übungsblätter 1-3 Holen Sie mehr aus sich raus! Toll! Super! Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-2 M. Philippsen Kapitel 10 - Abstrakte Datentypen 10.1 10.2 10.3 10.4 10.5 10.6 10.7 Einführung Programmentwicklung mit ADT Liste Keller Schlange Binärbaum Menge und Mehrfachmenge Handy aus! Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-3 M. Philippsen 10.1 Einführung Rückblick auf konkrete Datentypen (1) Ein Typ gibt an, welche konkreten Operationen auszuwählen sind. Stark typisierte Programmiersprachen erkennen Typfehler immer zur Übersetzungszeit Æ viele Programmierfehler können erkannt werden. Primitive Datentypen: y Jeder Ausdruck und jede Variable im Programm hat einen Typ. y Es gibt zu jedem primitiven Typ eine Menge von Operationen, die darauf ausgeführt werden können. y Die Wirkung der Operationen ist in der Sprachspezifikation erläutert. Klassen definieren Methoden, die auf ihren Objekten ausgeführt werden können. y Wenn (Instanz)variablen der Objekte verborgen sind, dann lässt sich der Objektzustand nur durch Methoden modifizieren und abfragen. y Aber: Wie ist die Wirkung der Methoden auf den Zustand spezifiziert? Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-4 M. Philippsen 10.1 Einführung Rückblick auf konkrete Datentypen (2) Steht im Speicher 2B = 0010 1011, kann das je nach Typ bedeuten: y y y y „+“ im ASCII-Code 43 als binär dargestellte Ganzzahl Subtraktionsbefehl auf Intel-Prozessoren … Je nach Typ sind unterschiedliche Operationen in der Sprachspezifikation erklärt y „+“ zur Addition von Ganzzahlen y „+“ zur Konkatenation von Zeichenfolgen Verhalten von Methoden vergleichsweise dürftig festgelegt. Beispiel: y uhr.setzeZeit(std,min) y uhr.anzeigen() Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-5 Verhalten ist nur durch Namen der Methoden angedeutet, eventuell im Kommentar. Es gibt bislang keine „saubere“ Spezifikation des Verhaltens! M. Philippsen 10.1 Einführung Rolle von Typen in Software-Systemen Komponente Komponente Komponente Komponenten, die andere Komponenten nutzen, müssen sich auf die Erfüllung der Aufgaben verlassen können! Kommunikation durch •Prozeduraufruf •Nachrichtenversand Komponente Komponente Komponente Software-System Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-6 M. Philippsen 10.1 Einführung Komponente/Modul y löst logisch und funktional zusammenhängende Aufgabe y besitzt Schnittstelle bestehend aus Funktionssignaturen und Zusicherungen über diese Funktionen, so dass à …das Modul von Dritten allein bei Kenntnis der Schnittstelle benutzt werden kann (also ohne Kenntnis der Implementierung (= des Quell-Codes)) à …das Modul allein bei Kenntnis der Schnittstelle implementiert werden kann (also ohne Kenntnis seiner Verwendung(en), des verwendenden Codes). Der Modul/Komponenten-Begriff ist grundlegend für die arbeitsteilige Konstruktion größerer Systeme (in allen Ingenieurdisziplinen). Die strikte Trennung von Implementierung und Verwendung heißt Geheimnisprinzip (= Implementierung geheim halten) oder Kapselung (der Implementierung gegen die Benutzung). Das Geheimnisprinzip erlaubt es, Implementierungen auszutauschen, ohne die Verwendung funktional zu beeinflussen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-7 M. Philippsen 10.1 Einführung Rolle von Typen in Software-Systemen Dienst Algorithmen und Datenstrukturen Außensicht Innensicht Dienst: y Von der Komponente garantierte, von ihr erfüllte Aufgaben. y Oder auch: Kompetenzen der Komponente. Diensteigenschaften: y Funktionale Eigenschaften (Dienstfunktionalität): Umfang und Wirkung der anforderbaren Aufgaben, Schnittstelle der Komponente. y Nichtfunktionale Eigenschaften (Dienstmerkmale oder Dienstqualitäten): Randbedingungen, die bei der Erfüllung der Aufgaben beachtet werden. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-8 M. Philippsen 10.1 Einführung Abstrakter Datentyp (ADT) = Die Schnittstelle einer Komponente und ihr Verhalten (ein Typ) wird ohne Angabe einer konkreten Implementierung (für alle Implementierungen gültig, also abstrakt) spezifiziert y Festlegung der auf dem Typ anwendbaren Operationen = Schnittstelle y Festlegung der Wirkung der Operationen Vorteile: y Nutzende Komponenten können sich auf die Spezifikation der Wirkung verlassen, ohne die Implementierung zu kennen. (Æ „Design by Contract“) y Die Implementierung einer Komponente ist für die Nutzer geheim. Sie kann ausgetauscht/verbessert werden, ohne dass der Nutzer betroffen ist, solange die spezifizierte Wirkung der Operationen erhalten bleibt. (Æ Geheimnisprinzip) y Nach der Implementierung der Operationen kann man nachweisen, dass das Verhalten spezifikationsgemäß ist. y Im Software-Entwicklungsprozess kann man das Nachdenken über Operationen und deren Wirkung von der Implementierung trennen. Man muss also nicht alle Probleme auf einmal lösen sondern kann schrittweise verfeinern. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-9 M. Philippsen 10.1 Einführung Signatur Die Signatur eines ADT legt fest, welche Operationen erlaubt sind, welche Typen die Parameter der Operationen haben müssen und von welchem Typ das Resultat ist. Signatur des ADT Boolean: y y y y y true: false: not: and: or: Boolean Boolean x Boolean Boolean x Boolean Typen der Parameter Æ Boolean Æ Boolean Æ Boolean Æ Boolean Æ Boolean 0-stellige Funktionen heißen Konstante Ergebnistyp Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-10 M. Philippsen 10.1 Einführung Axiome Axiome legen die Wirkung der Operationen fest, indem sie auf andere Funktionen zurückführen. Axiome des ADT Boolean: y y y y y y y A1 A2 A3 A4 A5 A6 A7 not(false) = true not(true) = false and(false,false) = false and(false,true) = false and(true,false) = false and(true,true) = true or(x,y) = not(and(not(x),not(y))) Name des Axioms Sonderfall der Rückführung: Spezifikation durch vollständige Aufzählung Man erkennt, dass es nur 2 Datenobjekte in diesem Datentyp gibt. Rückführung auf die Wirkung anderer Funktionen Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-11 M. Philippsen 10.1 Einführung Weitere ADT-Begriffe (1) Operationen, die Datenobjekte des Typs erzeugen, heißen Konstruktoren. Für einen ADT lässt sich eine Menge von Konstruktoren angeben, mit der alle möglichen Datenobjekte erzeugt werden können. Normalform eines Datenobjekts: konstruiert durch eine minimale Zahl von Konstruktoraufrufen. Die übrigen Konstruktoren heißen Hilfskonstruktoren. Operation, die Informationen über einen Datentyp oder ein Datenobjekt liefern, heißen Projektionen bzw. Selektionen Vergleiche ADT-Konstruktoren mit Konstruktoren in Java. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-12 M. Philippsen 10.1 Einführung Mit true und false lassen sich alle Datenobjekte darstellen Æ einzige Konstruktoren von Boolean. Normalform offensichtlich. Weiter ADT-Begriffe (2) Beim y Signatur à à à à à true: false: not: Boolean and: Boolean x Boolean or: Boolean x Boolean Æ Boolean Æ Boolean Æ Boolean Æ Boolean Æ Boolean y Axiome à à à à à à à A1 A2 A3 A4 A5 A6 A7 not(false) = true not(true) = false and(false,false) = false and(false,true) = false and(true,false) = false and(true,true) = true or(x,y) = not(and(not(x),not(y))) Übrige Operationen liefern Datenobjekt des Typs. Daher Hilfskonstruktoren. Hier keine Projektionen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-13 M. Philippsen 10.1 Einführung Die Wirkung von Folgen von Operationsaufrufen kann durch die Axiome auf die Normalform zurückgeführt werden. Normalform beim Datentyp Boolean am Beispiel: and(or(true,and(true,false)) , false) and(or(true, , false) //Anwendung A5 and(not(and(not(true),not(false))) , false) //Anwendung A7 and(not(and( false )), false) //Anwendung A1,A2 ), false) //Anwendung A4 , false) //Anwendung A1 and(not( and( false ) true false true false Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-14 //Anwendung A5 Normalform M. Philippsen 10.2 Programmentwicklung mit ADT Beispiel: Einsatz eines ADTs bei der Programmentwicklung Gesucht ist ein Programm, dass die deutsche Bedeutung englischer Wörter speichert und dann diesbezügliche Fragen beantworten kann. (Mit vielen sehr vereinfachenden Annahmen …) y y y y Ew: Menge der englischen Wörter Dw: Menge der deutschen Wörter Eingabe beim Speichern: endl. Menge von Wortpaaren (x,y) 0 Ew x Dw Ausgabe beim Abfragen von z 0 Ew: b 0 Dw c {?} mit b 0 Dw wenn (z,b) gelernt wurde und b=? sonst. Offensichtlich muss das Programm die Operationen „eintragen“ und „nachschlagen“ bewältigen, die auf einem Zustandsspeicher operieren. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-15 M. Philippsen 10.2 Programmentwicklung mit ADT Datentyp Wörterbuch (Ew, Dw) Signatur: y create: y enter: y find: Æ Wörterbuch Wörterbuch x Ew x Dw Æ Wörterbuch Wörterbuch x Ew Æ Dw c {?} create erschafft ein leeres Wörterbuch Axiome: y A1: y A2: 2 Konstruktoren, 1 Projektion find(create, z) = ? Zusammenhang zwischen enter und find y falls x=z find(d, z) sonst find(enter(d, x, y), z) = Die Kunst der Spezifikation besteht darin, genau das Wesentliche und nichts Überflüssiges zu sagen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-16 Rekursive Rückführung auf die Bedeutung eines kleineren Ausdrucks M. Philippsen 10.2 Programmentwicklung mit ADT Man kann zeigen, dass find(d,z) den letzten Eintrag für z findet, falls ein solcher existiert, und sonst „?“ liefert. Beweis per struktureller Induktion y Die einzige Chance, ein Wörterbuch „quasi aus dem Nichts“ zu erzeugen bietet die Operation create y Weitere Wörterbücher können nur durch die Operation enter entstehen. y Induktionsanfang: à Das Wörterbuch hat die Länge 0 und die Form create à Nach A1 hat find(create,z) das gewünschte Resultat. y Induktionsschluss: „n-1Æn“ à Das Wörterbuch hat die Form enter(enter(…enter(create,(x1,y1),…,(xn-1,yn-1),(xn,yn)) à Falls xn=z, dann liefert find aufgrund von A2 den letzten Eintrag von z ins Wörterbuch. à Andernfalls hat find in dem Wörterbuch der Länge n-1 nach Induktionsvoraussetzung das gewünschte Verhalten. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-17 M. Philippsen 10.2 Programmentwicklung mit ADT Nachdem die Wirkung der Operationen abstrakt festgelegt sind, kann man über die Implementierung nachdenken: Es gibt unterschiedliches Möglichkeiten y Liste, Suchbaum, … später mehr Hier Implementierung mit einer Reihung y feste maximale Länge oder Längenverdopplung bei Ausschöpfung y Implementierungsansatz 1: à Verweise auf die Wortpaare werden bei enter sequentiell aufsteigend in die Reihung eingetragen. à find sucht die Reihung rückwärts nach einem Treffer ab. y Implementierungsansatz 2: à Verweise auf die Wortpaare werden bei enter sequentiell aufsteigend in die Reihung eingetragen. Duplikate ersetzen den alten Eintrag vollständig. à find durchsucht die Reihung in beliebiger Reihenfolge nach einem Treffer. y Welcher Ansatz ist besser? Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-18 Anzahl Vergleiche im ?-Fall M. Philippsen Kapitel 10 – Abstrakte Datentypen 10.1 √ Einführung 10.2 √ Programmentwicklung mit ADT = Datentyp zur Speicherung, Organisation, Verwaltung von Objekten eines Elementdatentyps Im folgenden werden Behälterdatentypen als ADT formuliert. y Typ der Elemente im Behälter ist Parameter des ADT y Behälterdatentypen sind sehr bedeutsam für die Praxis 10.3 10.4 10.5 10.6 10.7 Liste Keller Schlange Binärbaum Menge und Mehrfachmenge Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-19 M. Philippsen 10.3 Liste Um mit Mengen von Datenelementen umzugehen, kann man ein- oder mehrdimensionale Reihungen benutzen. Für Reihungen muss man aber zum Erzeugungszeitpunkt angeben, wie viele Elemente gebraucht werden. y Falls das Feld zu klein ist, kann ein Programmfehler auftreten oder man muss extra Code zum Anlegen größerer Felder und Kopieren in diese schreiben (Laufzeit!) y Falls das Feld zu groß ist, wird unnötig Platz verschwendet. Dadurch werden evtl. andere Programme behindert, d. h. diese können nicht laufen oder laufen langsam (Æ Technische Informatik: 2 „Cache-Nutzung“ oder Æ Softwaresysteme 1: Seitenwechsel). y Falls Elemente in einer bestimmten Reihenfolge gehalten werden sollen, dann erfordert das Einfügen oder Löschen von Elementen in einem Feld Kopierarbeit. Listen vermeiden diese Nachteile: y Listen enthalten nicht mehr Elemente als nötig. y Listen können beliebig wachsen und schrumpfen. y Listen können an beliebiger Stelle Elemente einfügen oder entfernen, ohne dabei andere Elemente verlagern (kopieren) zu müssen. Listen haben aber einen Nachteil. Im Gegensatz zu Feldern gibt es keine Indizierungsoperation (z. B. adresse[9923]). Algorithmen, die eine Indizierung erfordern, laufen deshalb auf Listen nur langsam. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-20 M. Philippsen 10.3 Liste append Gedanklich: Pfeilrichtung wird klar bei Implementierung tail neuestes Element head Signatur Liste(T) y y y y y create: append: head: tail: length: T x Liste Liste Liste Liste Æ Liste Æ Liste ÆT Æ Liste Æù Konstruktoren Projektion Hilfskonstruktor Projektion Axiome y y y y A1: A2: A3: A4: head(append(x,l)) = x tail(append(x,l)) = l length(create) = 0 length(append(x,l))=1+length(l) head(create) und tail(create) sind nicht spezifiziert. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-21 M. Philippsen 10.3 Liste Parameterlose Operation Signaturdiagramm: head T append create Liste tail Typ Operation mit 2 Parametern length ù Hier könnte das Signaturdiagramm mit Operationen auf ù fortgesetzt werden. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-22 M. Philippsen 10.3 Liste Anmerkungen zur Normalform In welcher Reihenfolge auch immer Elemente per append an die Liste angefügt und per tail aus der Liste entfernt werden, die Normalform besteht stets aus der Listenerzeugung plus sequentieller Anfügung in der Listenreihenfolge. (Beweis mit struktureller Induktion) Beispiel: tail(append(B,append(A,create))) A B append(A append(B tail Entspricht in Normalform: append(A,create) Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-23 M. Philippsen 10.3 Liste Anmerkungen zur Implementierung Verschiedenste Implementierungsmöglichkeiten Hauptunterschiede: wie einfach gelangt man von der Position eines Listenelements zum Vorgänger/Nachfolger Erweiterung um diverse zusätzliche Operationen möglich/üblich: y Einfügen, Löschen an beliebiger Stelle im Inneren der Liste y Verketten zweier Listen y Zugriff auf Anfangs-/End-/Teillisten Diese Erweiterungen lassen sich stets auf eine Folge der obigen Elementaroperationen zurückführen (und können in diesem Sinne als Hilfskonstruktoren erklärt werden). Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-24 M. Philippsen 10.3 Liste Implementierungsbeispiel Liste class Element { int datum; Element voriges; } class Liste { Element kopf; kopf Element neuestes Element Liste append(Element neu) {…} Element head() {…} Liste() {…} int length() {…} } voriges voriges voriges Beachte: Dies ist ein Implementierungsbeispiel. Später lernen wir bessere Implementierung kennen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-25 M. Philippsen 10.3 Liste Implementierungsbeispiel „append“ class Liste { ... Liste append(Element neu) { neu.voriges = kopf; kopf = neu; return this; } } Liste kopf neu Element voriges voriges voriges voriges Verweis wird kopiert Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-26 M. Philippsen 10.3 Liste Implementierungsbeispiel „head“ class Liste { ... Element head() { return kopf; } } Liste kopf Element voriges Ein Verweis auf diese zuletzt eingefügte Listenelement wird geliefert. voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-27 M. Philippsen 10.3 Liste Implementierungsbeispiel „tail“ class Liste { ... Liste tail() { if (kopf != null) kopf = kopf.voriges; return this; } } Liste kopf Element voriges voriges voriges tail ist auf leerer Liste nicht definiert. Schutzabfrage. Später besser. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-28 Der Speicherbereiniger entfernt den früheren Listenkopf (irgendwann) M. Philippsen 10.3 Liste Implementierungsbeispiel „length“ class Liste { ... //rekursiver Ansatz int length() { return length(kopf); } private int length(Element e) { if (e == null) { return 0; } else { return 1+length(e.voriges); } } } Liste kopf Element 1+… 3 voriges 2 voriges 1+… 1 1+… voriges 0 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-29 M. Philippsen 10.3 Liste Implementierungsbeispiel „length“ class Liste { ... //entrekursivierte Fassung int length() { int len = 0; Element e = kopf; while (e != null) { e = e.voriges; len += 1; } return len; } } Liste kopf Element 0, e voriges 1, e voriges 2, e voriges 3, e Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-30 M. Philippsen 10.3 Liste Implementierungsbeispiel „reverse“ class Liste { ... Liste reverse() { Liste neueListe = new Liste(); while (kopf != null) { neueListe.append(kopf); tail(); } return neueListe; } } Liste kopf Element voriges voriges voriges Was ist hier falsch? Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-31 M. Philippsen 10.3 Liste Implementierungsbeispiel „reverse“ - Fehlersuche (1) Liste Liste reverse() { Liste neueListe = new Liste(); while (kopf != null) { neueListe.append(kopf); tail(); } return neueListe; } Liste append(Element neu) { neu.voriges = kopf; kopf = neu; return this; } kopf Element voriges voriges voriges neueListe kopf Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-32 M. Philippsen 10.3 Liste Implementierungsbeispiel „reverse“ - Fehlersuche (2) Liste Liste reverse() { Liste neueListe = new Liste(); while (kopf != null) { neueListe.append(kopf); tail(); } return neueListe; } Liste append(Element neu) { neu.voriges = kopf; kopf = neu; return this; } kopf Element voriges verwaist: voriges neueListe kopf voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-33 M. Philippsen 10.3 Liste Implementierungsbeispiel „reverse“ - korrigiert Liste class Liste { ... Liste reverse() { Liste neueListe = new Liste(); while (kopf != null) { Element e = kopf;//bzw head() tail(); //Zeiger in e //noch korrekt neueListe.append(e); } return neueListe; } } kopf Element voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-34 M. Philippsen 10.3 Liste Orthogonale Liste (1) Listenelemente gleichzeitig in mehreren Listen führen. Beispiel: dünnbesetzte Matrix Spaltenköpfe … 2.3 2.5 0 0 0 0 0 0 0 0 0 4.1 0 0 0 5.7 0 … 0 … 0 … 0 … … Annahme: weniger als 1% der Matrix-Elemente sind ungleich Null 1.0 2.3 Zeilenköpfe 1.0 0 1.3 0 … 2.5 1.3 4.1 5.7 … Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-35 M. Philippsen 10.3 Liste Orthogonale Liste (2) Listenelemente gleichzeitig in mehreren Listen führen. Beispiel: dünnbesetzte Matrix Spaltenköpfe … Zeilenköpfe 1.0 2.3 2.5 1.3 4.1 Jedes Element speichert: • Zeilenindex • Zeilennächster • Spaltenindex • Spaltennächster 5.7 … Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-36 M. Philippsen 10.3 Liste Übliche Erweiterungen des bisherigen ADT Liste Konzept des Positionszeigers, der auf ein Element der Liste zeigt. y advance: Liste Æ Liste y restore: Liste Æ Liste y insert: T x Liste Æ Liste y delete: Liste Æ Liste y element: Liste Æ T y endpos: Liste Æ Bool rückt der Positionszeiger ein Element weiter setzt Positionszeiger auf Anfang zurück fügt an der Stelle des Positionszeigers ein neues Element ein löscht das Element aus der Liste, auf das der Positionszeiger verweist. liefert das Element, auf das der Positionszeiger verweist. true, falls der Positionszeiger auf das letzte Listenelement zeigt. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-37 M. Philippsen 10.4 Keller/Stapel („stack“) Gedanklich Entfernte Elemente 4. Eingefügte Elemente 4. 3. 2. 1. Keller Das zuletzt eingefügte Element kommt als 1. heraus. 4. 3. 2. 1. • Letzter-Zuerst-Strategie („last in first out“, LIFO) • Wenden eines Zugs über ein Abstellgleis Auslesen liefert das zuletzt eingefügte Element. Entfernen entfernt das zuletzt eingefügte Element. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-38 M. Philippsen 10.4 Keller/Stapel („stack“) Signatur Keller(T) y y y y y create: push: pop: top: empty: T x Keller Keller Keller Keller Æ Keller Æ Keller Æ Keller ÆT Æ Boolean Axiome für LIFOVerhalten Axiome: y y y y A1: A2: A3: A4: pop(push(x,s)) = s top(push(x,s)) = x empty(create) = true empty(push(x,s)) = false Ebenso wie tail eine verkürzte Liste zurück gibt, liefert pop einen Keller ohne das oberste Element. Normalform: nur create und push sind Konstruktoren. LIFO-Eigenschaft mit vollständiger Induktion beweisbar. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-39 M. Philippsen 10.4 Keller/Stapel („stack“) Signaturdiagramm: top T push create Keller empty true Bool pop false Hier mit Teilen des Signaturdiagramms von Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-40 M. Philippsen 10.4 Keller/Stapel („stack“) Kellerimplementierung mit einer Liste Abbildung: y y y y y y createKeller = createListe push(x,s) = append(x,s) pop(append(x,s)) = s top(append(x,s)) = x empty(create) = true empty(append(x,s)) = false Der ADT Keller wird hier auf den ADT Liste zurückgeführt: es ist angegeben, wie man grundsätzlich mit jeder korrekt implementierten Liste einen Keller implementieren kann. Beispiel: top(push(x,s)) = top(append(x,s)) = x //Nachweis der Keller-Eigenschaften trivial Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-41 M. Philippsen 10.4 Keller/Stapel („stack“) Keller werden benötigt zur Rückstellung von (Teil-)Problemen, die man später bearbeiten oder vervollständigen will. Zum Beispiel: y zur Implementierung der Rekursion, y zur Verarbeitung von Klammerstrukturen y zur Bearbeitung von Bäumen (in späterem Kapitel der Vorlesung) Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-42 M. Philippsen 10.4 Keller/Stapel („stack“) Keller zur Implementierung geschachtelter Methodenaufrufe Für jeden Methodenaufruf wird eine Methodenschachtel angelegt. Schachteln werden nach LIFO-Strategie wieder freigegeben. m() { ... n(); ... } m()-Aufruf n() { ... o(); ... } n()-Aufruf m n m Rücksprungadresse o()-Aufruf Keller der MethodenSchachteln bis zum o Aufruf von o. n m Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-43 M. Philippsen 10.4 Keller/Stapel („stack“) Keller zur Auswertung arithmetischer Ausdrücke in Postfixform Arithmetischer Ausdruck: 5 * (7 - 3) Postfixform: 573-* Ablauf: y y y y Kellermaschine Operanden auf den Keller legen, bis Operator erreicht Dann zwei Operanden vom Keller nehmen, Ergebnis berechnen Ergebnis auf den Keller legen, u.s.w. push 5 push 7 push 3 5 7 5 3 7 5 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-44 top, pop, top,pop, top, pop, top,pop, push (7-3) push (5*4) 4 5 20 M. Philippsen 10.4 Keller/Stapel („stack“) Fakultätsfunktion mit expliziter Kellerung Original: n wird auf den Keller gelegt. long fakultaet (int n) { return (n == 0) ? 1 : n*fakultaet(n-1); } Alle Kellerelemente zusammen multiplizieren fakultaet(4) while (!keller.empty()) ergebnis *= keller.topAndPop(); push 4 push 3 push 2 4 3 4 2 3 4 top,pop erg = 2 top,pop erg = 6 3 4 top,pop erg = 24 4 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-45 M. Philippsen 10.4 Keller/Stapel („stack“) Anmerkung zur Implementierung Die Listenimplementierung aus Abschnitt 10.3 funktioniert bereits nach dem LIFO-Prinzip. Sie ist leicht in eine Keller-Implementierung umzuwandeln. (Bei anderen Implementierungsweisen ggf. schwerer.) Speicherbereiche werden in der Regel durch eine Reihung und einen Stapel-Zeiger realisiert: 0 n push E SP pop 0 n E SP Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-46 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Gedanklich Ende Kopf enqueue Hinzufügen des neuesten Elements Erster-Zuerst-Strategie („first in first out“, FIFO) dequeue Wegnehmen des ältesten Elements y Im Unterschied zu Kellern, bei denen man Elemente an einem Ende sowohl anfügt als auch wegnimmt, geschieht bei Schlangen das Hinzufügen an einem und das Wegnehmen am anderen Ende. Signatur Schlange(T) y y y y y create: enq: front: deq: empty: T x Schlange Schlange Schlange Schlange Æ Schlange Æ Schlange ÆT Æ Schlange Æ Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-47 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Beispiel Schlange Aufbau einer Schlange y enq(2,enq(1,create)) 1 create enq(1,… Arbeiten auf der Schlange y deq(enq(2,enq(1,create))) 2 1 enq(2,… 2 deq(enq(2,… = enq(2, create)) y front(enq(2,enq(1,create))) =1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-48 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Axiome y A1: deq(enq(x,q)) = q falls empty(q) enq(x,deq(q)) sonst Für eine nicht-leere Schlage ist es unerheblich, ob man zuerst ein Element anhängt und dann eines wegnimmt oder umgekehrt. y A2: front(enq(x,q)) = x falls empty(q) front(q) sonst Das vorderste (älteste) Element einer Schlange ist unabhängig davon, ob noch weitere Element mittels enq angehängt sind. y A3: y A4: empty(create) = true empty(enq(x,q)) = false Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-49 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Normalform: nur create und enq sind Konstruktoren. FIFO-Eigenschaft per vollständiger Induktion beweisbar. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-50 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Signaturdiagramm: front T enq create Queue empty true Bool deq false Hier mit Teilen des Signaturdiagramms von Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-51 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schlangenimplementierung mit einer Liste (1) Abbildung: y createSchlange = createListe y deq(append(x,q)) = q y front(append(x,q)) = x append(x,createListe) falls empty(q) y enq(x,q) = append(y,enq(x,l)) sonst, mit q=append(y,l) y empty(create) = true Das neue Element x wird durch diese y empty(append(x,s)) = false rekursive Definition bis zum Ende der resultierenden Liste „geschoben“, aus der es als letztes herausgeholt wird. Korrektheit der Abbildung ist leicht durch Einsetzen nachzuweisen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-52 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schlangenimplementierung mit einer Liste (2) append(x,createListe) falls empty(q) enq(x,q) = append(y,enq(x,l)) Beispiel: enq(2,enq(1,createSchlange)) append(1,createListe) enq(2, falls q=append(y,l) 1 ) front würde 1 liefern, FIFO append(1,enq(2,createListe)) append(2,createListe) append(1, ) 2 2 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-53 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schlangen werden zur Abarbeitung von Aufträgen in Eingangsreihenfolge verwendet: y y y y y y Prozessverwaltung im Betriebssystem Speicherverwaltung Druckaufträge Kommunikationssoftware Tastaturpuffer … Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-54 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkung zur Implementierung (1) Schlange Schlangen werden mit zusätzlichem Zeiger auf das Schlusselement implementiert. Leere Schlange: kopf=ende=null kopf ende Einelementige Schlange: Sowohl kopf als auch ende zeigen auf dasselbe einzige Schlangenelement. enq: voriges-Verweis des bisherigen ende-Elements auf das neue Element zeigen lassen. Dann ende-Verweis der Schlange auf das neue Element setzen. Element voriges voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-55 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkung zur Implementierung (2) deq: kopf-Verweis auf den Nachfolger des aktuellen Kopfs versetzen. Achtung: wenn die Schlange nur ein Element hatte, dann zeigt ende-Verweis danach noch auf das entfernte Element. ende-Verweis muss ebenfalls auf null gesetzt werden. Schlange kopf ende Element voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-56 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Ähnlich wie beim Keller kann auch eine Reihung/ein Speicherbereich zur Schlangenimplementierungen verwendet werden: 0 n F enq E kopf ende 0 n F deq E ende kopf 0 n E kopf Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-57 ende M. Philippsen 10.5 Schlange/Warteschlange („queue“) „Zirkuläre Reihung“ 0 ende Das erst Element folgt auf das letzte. Für jeden Index ist die nächste Position modulo der max. Schlangengröße. Man benötigt eine logische Variable voll, um den Zustand der Schlange zu protokollieren. F E kopf Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-58 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Prioritätswarteschlange („priority queue“) Die Elemente haben eine Priorität. Beim Auslesen wird nicht das am längsten in der Schlange befindliche Element (FIFO) geliefert, sondern das Element höchster Priorität, das am längsten in der Schlange war. Beispiel: y Lebensalter y Kreditwünsche nach Höhe Elemente haben den Typ (T,ù) Signatur Schlange(T,ù) y y y y y create: enq: front: deq: empty: T x ù x Schlange Schlange Schlange Schlange Æ Schlange Æ Schlange ÆTxù Æ Schlange Æ Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-59 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Beispiel Prioritätswarteschlange Aufbau einer Prioritätswarteschlange y enq((x,3),enq((b,2),enq((v,3),enq((a,2),create)))) a2 create v3 a2 enq((a,2)… enq((v,3),… b2 v3 a2 enq((b,2),… x3 b2 v3 a2 enq((x,3),… Arbeiten auf der Schlange y front(deq(…siehe oben…)) front x3 b2 v3 a2 = (x,3) front x3 b2 a2 deq(… Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-60 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Prioritätswarteschlange („priority queue“) Zusätzlich erforderliche Operation: y maxprio: Schlange Æù Æ maxprio gehört nicht zur Signatur der Prioritätswarteschlange, weil kein Benutzer der Prioritätswarteschlange den Wert von maxprio wissen muss. Æ In Java: maxprio als private Methode vereinbaren! Zugehöriges Axiom: y A5: maxprio(enq((x,g),q) = g g maxprio(q) falls empty(q) falls maxprio(q)<g sonst Paar (Element, Priorität) Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-61 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Axiom der Schlange y A1: q falls empty(q) enq(x,deq(q)) sonst deq(enq(x,q)) = Für eine nicht-leere Schlange ist es unerheblich, ob man zuerst ein Element anhängt und dann eines wegnimmt oder umgekehrt. Axiom der Prioritätswarteschlange y A1: deq(enq((x,g),q)) = Falls (x,g) höchste Priorität hat, entfernt deq dieses Paar. q q enq((x,g),deq(q)) falls empty(q) falls maxprio(q)<g sonst Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-62 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Axiom der Schlange y A2: x falls empty(q) front(q) sonst front(enq(x,q)) = Das vorderste (älteste) Element einer Schlange ist unabhängig davon, ob noch weitere Element mittels enq angehängt sind. Axiom der Prioritätswarteschlange y A2: (x,g) front(enq((x,g),q)) = (x,g) front(q) Falls (x,g) höchste Priorität hat, liefert front dieses Paar. falls empty(q) falls maxprio(q)<g sonst Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-63 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Implementierung einer Prioritätswarteschlange mit einer Liste Jetzt: Einfügen sortiert nach Priorität, keine Hilfsoperation maxprio Abbildung: y createSchlange = createListe y deq(append((x,g),q)) = q y front(append((x,g),q)) = (x,g) append((x,g),createListe) y enq((x,g),q) = append((x,g),q) append(y,enq((x,g),l)) y empty(create) = true y empty(append((x,g),s)) = false Falls (x,g) höchste Priorität hat, einfach an Liste anhängen falls empty(q) falls front(q).gewicht<g sonst, mit q=append(y,l) Sonst Listenkopf überspringen und in q gemäß Sortierung einfügen Korrektheit der Abbildung ist leicht durch Einsetzen nachweisbar. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-64 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung Einsetzen eines Elements in eine Warteschlange y Leere Schlange kopf ende kopf ende voriges y Nicht-leere Schlange à als neuen Kopf voriges kopf ende voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-65 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung (2) Einsetzen eines Elements in eine Warteschlange y Nicht-leere Schlange à in der Mitte voriges kopf ende voriges voriges Das Einsetzen erfolgt immer nach einem vorhandenen Element. à am Ende kopf ende voriges voriges voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-66 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schleppzeiger (1) Beim Implementieren einer Prioritätswarteschlange sucht man die Stelle zum sortierten Einfügen eines neuen Elements. Mit einem Verweis läuft man die Schlange ab, bis man ein Element kleinerer Priorität gefunden hat. Das Einfügen muss aber vor diesem Element erfolgen. kopf ende 100 voriges 85 (neu) voriges 100<85? 90 voriges 90<85? Æ Benutze Verweis, der stets um ein Element hinter Lauf-Verweis zurück ist 80 voriges 80<85? Neues Element ist vor diesem Element einzusetzen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-67 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schleppzeiger (2) Wenn man wirklich will, dann kann man ohne Schleppzeiger auskommen. Wie? Element laufZeiger = kopf; Element schleppZeiger = null; while ((laufZeiger != null) && (laufZeiger.prio >= neu.prio)) { schleppZeiger = laufZeiger; laufZeiger = laufZeiger.voriges; } ... kopf ende 85 (neu) voriges 100 voriges 90 voriges 100<85? SL SL 90<85? 80 voriges SL 80<85? Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-68 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung (3) Entfernen eines Elements aus einer nicht-leeren Warteschlange y am Anfang kopf ende kopieren voriges voriges voriges voriges-Verweis des ersten/zu löschenden Schlangenelements wird in kopf kopiert. Erstes Schlangenelement ist anschließend verwaist und kann vom Speicherbereiniger entfernt werden. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-69 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung (4) Entfernen eines Elements aus einer nicht-leeren Warteschlange y in der Mitte kopf ende kopieren voriges y am Ende kopf ende voriges voriges kopieren voriges voriges voriges Schleppzeiger ist notwendig Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-70 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Doppelte Verkettung Die Verzeigerung der Elemente nur in eine Richtung erfordert einen Schleppzeiger wenn auf das „vorhergehende“ Element zugegriffen werden soll. Das Durchlaufen der Schlange in umgekehrter Richtung erfordert eine umständliche Umordnung der Elemente in eine neue Liste Besser: Verweis auf Vorgänger und Nachfolger ? voriges nächstes voriges nächstes voriges nächstes ? Unterschiedliche Möglichkeiten für Zeiger an Enden der Schlange: - zyklische Verkettung/zirkuläre Liste - null als Markierung Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-71 M. Philippsen Kapitel 10 – Abstrakte Datentypen 10.1 √ Einführung 10.2 √ Programmentwicklung mit ADT Im folgenden werden Behälterdatentypen als ADT formuliert. y Typ der Elemente im Behälter ist Parameter des ADT y Behälterdatentypen sind sehr bedeutsam für die Praxis 10.3 √ 10.4 √ 10.5 √ 10.6 10.7 Liste Lineare Datentypen, lassen sich auf Keller eine Liste zurückführen Schlange Binärbaum Menge und Mehrfachmenge Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-72 M. Philippsen 17.1 Graph-Grundlagen Ein stark zusammenhängender ungerichteter Graph heißt Baum, wenn es keine Schlingen gibt und wenn es zwischen je zwei verschiedenen Knoten genau einen einfachen Pfad gibt. Bei gerichteten Graphen sind mehr Begriffe nötig: y Gerichteter azyklischer Graph (DAG, „directed acyclic graph“): Gerichteter Graph ohne Zyklen. y Ein Knoten v eines DAG heißt Wurzel, falls es keine auf ihn gerichteten Kanten gibt. Hat ein DAG nur eine Wurzel, so heißt er Wurzelgraph. Wurzelgraph: DAG: Wurzel X Wurzel nur zyklenfrei, wenn X entfernt ist. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie Wurzel M. Philippsen 17.1 Graph-Grundlagen Bei gerichteten Graphen ist ein Baum ein Wurzelgraph, in dem zu jedem Knoten genau ein (eindeutiger) Pfad von der Wurzel aus führt. Baum: Wurzel X X Es gibt noch andere Möglichkeiten, um durch Entfernen von Kanten aus dem Graph ein Baum zu machen. Ein DAG mit mehreren Wurzeln, aber eindeutigen Pfaden, heißt Wald. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Aus dieser Baum-Definition folgt: y Es gibt (auch bei gerichteten Graphen) keinen Zyklus. y Die Wurzel ist der einzige Knoten ohne direkten Vorgänger. y Jeder andere Knoten hat genau einen direkten Vorgänger, er kann aber beliebig viele direkte Nachfolger haben. Abweichend zu ungerichteten Graphen definiert man: y Der Grad eines Knotens ist die Anzahl der Nachfolger eines Knotens. (Es werden also nur die Ausgangskanten berücksichtigt.) y Der Grad des Baums ist der maximale Grad seiner Knoten. y Ein Knoten mit Grad 0, also ohne Nachfolger, heißt Blatt. y Alle anderen Knoten heißen innere Knoten des Baums. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Weitere Baum-Begriffe (1) Binärbaum = Baum mit Grad 2 y Jeder Knoten hat maximal 2 Nachfolger. y Man spricht vom rechten/linken Kind (Nachfolger, Sohn). y Wenn bei der graphischen Darstellung von Bäumen klar ist, welcher Knoten die Wurzel ist (und welche Richtung die Kante zwischen Elternknoten und Kinderknoten hat), kann man auf die Pfeilspitzen verzichten. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Weitere Baum-Begriffe (2) Der Unterbaum eines Knotens v im Baum sind v und alle nachfolgenden Knoten plus die verbindenden Kanten. y Unterbäume sind wieder Bäume. Triviale Bäume: leerer Graph; kantenloser Graph mit nur einem Knoten. Die Länge des Pfades von der Wurzel zu einem Knoten k bestimmt die Höhe von k im Baum. y Die Wurzel hat die Höhe 0. y Die Höhe aller direkten Nachfolger eines Knotens v ist um 1 größer als die Höhe von v. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Am Beispiel: 1:2 0:1 Wurzel innerer Knoten 2:0 2:1 4:0 Blatt 3:1 n:m = Höhe:Grad Blatt Unterbaum dieses Knotens: 0:1 2:0 Grad des Baums: 2 1:1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Beispiele: Ausdrucksbaum „Kantorowitsch-Baum“ 5 * (7-3) Cecilia Claude * 7 Elisabeth Elisabeth II Mary Georg VI George V - 5 Abstammungsbaum 3 Victoria Loius Alice Olga Georg I Andrew Charles Philip ist Kind von Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen Andere Darstellungsformen von Bäumen Kontour-Darstellung ▪ Einrückungsdarstellung A B H J D B A F C H J G E C D E G F Listendarstellung A(B(HJ)C( DE( G)F )) Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 10.6 Binärbaum Signatur BinBaum(T) y y y y y y create: bin: left: right: value: empty: BinBaum x T x BinBaum BinBaum BinBaum BinBaum BinBaum Æ BinBaum Æ BinBaum Æ BinBaum Æ BinBaum ÆT Æ Boolean Axiome: y y y y y A1: A2: A3: A4: A5: left(bin(x,b,y)) = x right(bin(x,b,y)) = y value(bin(x,b,y)) = b empty(create) = true empty(bin(x,b,y)) = false Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-81 M. Philippsen 10.6 Binärbaum Beispiel Binärbaum Hilfefunktion: leaf v = bin(create,v,create) //erzeuge Blatt value(left(bin(leaf(3),2,leaf(4)))) leaf(3) leaf(4) 3 =3 2 bin(..2..) 3 4 3 empty(left(left(…obiger Baum…)) 2 3 left(..) 4 4 3 = true left(..) 3 left(..) Die „leeren Nachfolger“ der Blätter zählen bei der Baumhöhe nicht mit. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-82 M. Philippsen 10.6 Binärbaum Signaturdiagramm: value T bin create BinTree empty true Bool left,right false dreistellige Operation Hier mit Teilen des Signaturdiagramms von Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-83 M. Philippsen 10.6 Binärbaum Anmerkungen zur Implementierung (1) Explizite Darstellung mit Verweisen y Verweise von Knoten zu Nachfolgern/Kindern/Söhnen Reihung von Verweisen, maximaler Knotengrad legt Länge der Reihung fest. Binärbaum: 2 y Verweise auf Vorgänger/Elternknoten/Vater Allgemeine Bäume: bei stark schwankendem Grad, kann ggf. Liste mit Verweisen günstiger sein. y beide Sorten von Verweisen Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-84 Kanten im Baum M. Philippsen 10.6 Binärbaum Anmerkungen zur Implementierung/beliebiger Grad (2) Explizite Darstellung mit Verweisen y Mit maximal 2 Verweisen: Ein Knoten zeigt nur auf einen Nachfolger, der dann die Geschwisterknoten verkettet nicht sinnvoll für Binärbäume zeigt auf Geschwisterknoten zeigt auf Kind Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-85 M. Philippsen 10.6 Binärbaum Anmerkung zur Implementierung (3) Mit Reihungen und Indizes, ohne explizite Verweise A B D C E F G für allgemeine Bäume: mehr Zeilen A B C D E F G 0 1 2 3 4 5 6 zugeordneter Index 1 2 3 -1 -1 5 -1 -1 Index linkes Kind 4 -1 -1 6 -1 -1 Index rechtes Kind -1 steht für: kein Nachfolger vorhanden Während die strukturverändernden Operationen des ADT bei Speicherung mit Verweisen relativ leicht machbar sind, müssen hier die Index-Reihungen i.A. größtenteils ersetzt werden. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-86 M. Philippsen 10.6 Binärbaum Anmerkungen zur Implementierung (4) Implizite Darstellung: y Es werden keine Verweise/keine Index-Reihungen verwendet. Durch die Position in einem Feld kann Position der Nachfolger berechnet werden. à à à à Speichere Wurzel in A[1] Linker Nachfolger von Knoten i steht in A[2*i] Rechter Nachfolger von Knoten i steht in A[2*i+1] Der Vorgänger eines Knotens k steht in A[k/2] y Beispiel: Binärbaum: A B D 1 3 4 5 6 7 A B C D E F G C E F 2 anderer Faktor für allgemeine Bäume G Gut bei ausbalancierten Binärbäumen. Strukturänderungen sind noch mehr Aufwand als bei den Index-Reihungen. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-87 M. Philippsen 10.6 Binärbaum Haldenspeicherung Die implizite Darstellung eines Baums in einer Reihung wird oft verwendet, um eine Halde („heap“) zu speichern. Halden sind ideal zur Implementierung von Prioritätswarteschlangen. Haldeneigenschaft: Eine Halde zeichnet sich dadurch aus, dass der Wert eines Knotens größer oder gleich dem Wert seiner zwei Nachfolger ist. (Analog mit ≤ definierbar.) Nachfolge von A[1] A[1] A[2] A[3] A[4] … A[k] … A[n] Der Knoten mit maximalem Wert ist immer an der Spitze der Halde. derzeit k Elemente auf Halde maximaler Füllstand der Halde Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-88 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde Der Knoten (mit höchster Priorität) wird vorne aus der Halde entfernt. y Jetzt sind in der Reihung A[2...k] zwei Halden gespeichert. Eine beginnt an Position A[2], die andere an Position A[3]. Der letzte Knoten A[k] wird an die Spitze der Halde kopiert. y Jetzt gilt i.A. nicht mehr, dass A[1] ≥ A[2] und A[1] ≥ A[3]. A[1] ist i.A. an der falschen Position. y A[1] wird mit seinen beiden Nachfolgern verglichen und mit dem größeren von beiden vertauscht. Sei dies j. y Danach erfüllen A[1..3] die Haldeneigenschaft. y Jetzt gilt i.A. nicht mehr, dass A[j] ≥ A[2j] und A[j] ≥ A[2j+1] y Wiederhole Vertauschung mit maximalem Nachfolger rekursiv bis die Haldeneigenschaft erfüllt ist. Im schlimmsten Fall sind 2·log2k Vergleiche nötig, bis die Haldeneigenschaft wieder erfüllt ist. Bei der Implementierung der Prioritätswarteschlange mit einer Liste sind i.A. k Schritt nötig. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-89 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 16 15 13 14 10 9 12 6 5 16 ≥ 15 16 ≥ 13 15 ≥ 14 15 ≥ 10 13 ≥ 9 13 ≥ 12 14 ≥ 14 ≥ 10 ≥ 10 ≥ 9≥ 9≥ 6 7 3 2 5 7 11 8 1 Erfüllt die Haldeneigenschaft 3 2 … 4 4 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-90 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (2) 16 < > 13 15 > < 14 10 < > < 6 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 < 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-91 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (3) 1 < > 13 15 > < 14 10 < > < 6 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-92 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (4) 15 < > 13 1 > < 14 10 < > < 6 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-93 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (5) 15 < > 13 14 > < 1 10 < > < 6 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-94 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (6) 15 < > 13 14 > < 6 10 < > < 1 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-95 M. Philippsen 10.6 Binärbaum Entnahme aus der Halde am Beispiel (7) 5 6 7 8 9 10 11 12 13 14 15 16 16 15 13 14 10 9 12 6 5 7 3 2 4 11 8 1 15 13 14 10 9 12 6 5 7 3 2 4 11 8 1 1 15 13 14 10 9 12 6 5 7 3 2 4 11 8 15 1 9 12 6 5 7 3 2 4 11 8 1 2 3 4 13 14 10 15 14 13 1 10 9 12 6 5 7 3 2 4 11 8 15 14 13 6 10 9 12 1 5 7 3 2 4 11 8 Maximalelement wieder vorne. Erfüllt die Haldeneigenschaft Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-96 M. Philippsen 10.6 Binärbaum Einfügen in eine Halde Einfügen hat ähnliche Grundidee, wie Entfernen Neues Element wird als A[k+1] in die Halde geschrieben. y Falls der Wert des neuen Knotens größer ist als der seines Elternknotens (dieser sei j) dann wird getauscht. y Anschließend wird der neue Wert von j rekursiv mit dessen Eltern verglichen und ggf. getauscht. Im schlimmsten Fall sind log2k Vergleiche nötig, bis die Haldeneigenschaft wieder erfüllt ist. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-97 M. Philippsen 10.6 Binärbaum Einfügen in die Halde am Beispiel (1) 15 < > 13 14 > < 6 10 < > < 1 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 16 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-98 M. Philippsen 10.6 Binärbaum Einfügen in die Halde am Beispiel (2) 16 < > 13 15 > < 14 10 < > < 6 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 < 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-99 M. Philippsen 10.6 Binärbaum Einfügen in die Halde am Beispiel (1) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 15 14 13 6 10 9 12 1 5 7 3 2 4 11 8 15 14 13 6 10 9 12 1 5 7 3 2 4 11 8 16 15 14 13 6 10 9 12 1 5 7 3 2 4 11 8 16 15 14 13 6 10 9 12 16 5 7 3 2 4 11 8 1 15 14 13 16 10 9 12 6 5 7 3 2 4 11 8 1 15 16 13 14 10 9 12 6 5 7 3 2 4 11 8 1 16 15 13 14 10 9 12 6 5 7 3 2 4 11 8 1 Maximalelement wieder vorne. Erfüllt die Haldeneigenschaft Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-100 M. Philippsen 10.6 Binärbaum Binärer Suchbaum = Binärbaum, für dessen Knoten k gilt value(left) < value(k) < value(right), falls die Kinder existieren. Es muss eine (totale) Ordnungsrelation ≤ auf dem Elementtyp T existieren, damit man die Werte der Knoten vergleichen kann. 6 Beispiel < < 3 < 1 < 4 < 10 8 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-101 M. Philippsen 10.6 Binärbaum Signatur SuchBaum(T), T mit Ordnungsrelation: y y y y create: insert: find: delete T x BinTree T x BinTree T x BinTree Æ Æ Æ Æ BinTree BinTree Boolean BinTree Signaturen bin, left, right, value und empty des (normalen) Binärbaums werden verborgen. Ein ADT-Benutzer kann nur mit insert und delete auf dem Baum arbeiten. Zur Implementierung von insert und delete können die Signaturen des normalen Binärbaums verwendet werden, solange sichergestellt ist, dass sowohl insert als auch delete die Eigenschaft „binärer Suchbaum“ erhält. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-102 M. Philippsen 10.6 Binärbaum Zusätzliche Axiome von SuchBaum(T): y Aa: insert(x,create) = bin(create,x,create) y Ab: bin(b1,v,b2) insert(x,bin(b1,v,b2)) = bin(insert(x,b1),v,b2) bin(b1,v,insert(x,b2)) y Ac: find(x,create) = false y Ad: find(x,bin(b1,v,b2)) = true find(x,b1) find(x,b2) falls x=v falls x<v falls x>v falls x=v falls x<v falls x>v Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-103 M. Philippsen 10.6 Binärbaum Suchbäume sehen je nach Einfügereihenfolge anders aus insert(3,insert(5,insert(2,insert(4,create)))) 4 2 5 3 insert(5,insert(3,insert(4,insert(2,create)))) Wurzel 2 4 3 5 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-104 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Mengen sind einer der am häufigsten vorkommenden ADT Es gibt zahlreiche Implementierungsmöglichkeiten Signatur Menge(T), für T muss Gleichheitsoperator definiert sein y y y y y create: add: isIn: del: empty: T x Menge T x Menge T x Menge Menge Æ Menge Æ Menge Æ Boolean Æ Menge Æ Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-105 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Beispiel Menge: Mengen haben keine Duplikate add(a,add(a,add(b,create))) b add(b add(a a b add(a a b isIn(c, …Menge von oben…) c…a Æ isIn(c,add(b,create)) c…b Æ isIn(c,create) = false Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-106 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Axiome y A1: y A2: y A3: y A4: y A5: y A6: y A7: isIn(x,create) = false true falls x=y isIn(x,m) sonst add(x,m) falls x=y add(y,add(x,m)) sonst m falls x=y add(y,del(x,m)) sonst isIn(x,add(y,m)) = empty(create) = true empty(add(x,m)) = false add(x,add(y,m)) = del(x,create) = create del(x,add(y,m)) = Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-107 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Alternative mit weiteren Operationen Signatur Menge(T), für T muss Gleichheitsoperator definiert sein y y y y y create: add: isIn: del: empty: y y y y single: T union: Menge x Menge intersect: Menge x Menge diff: Menge x Menge T x Menge T x Menge T x Menge Menge Æ Menge Æ Menge Æ Boolean Æ Menge Æ Boolean Æ Menge Æ Menge Æ Menge Æ Menge Erzeugt einelementige Menge nicht immer vorhanden. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-108 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Beispiel erweiterter ADT Menge: union(add(a,add(b,create)), add(c,create)) b add(a add(b a b union c b a c add(c Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-109 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Axiome zu den alternativen Signaturen (1) y A1-A4 bleiben unverändert (isIn, empty) y A5: y A6: y A7: single(x) = add(x,create) add(x,m) = union(single(x),m) del(x,m) = diff(m,single(x)) y A8: union(create,s) = s y A9: y A10: y A11: „schlankere“ Axiome union(m,n) falls isIn(x,n) add(x,union(m,n)) sonst union(add(x,m),n) = intersect(create,m) = create add(x, intersect(m,n)) intersect(add(x,m),n) = intersect(m,n) falls isIn(x,n) sonst Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-110 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Axiome zu den alternativen Signaturen (2) y A12: y A13: diff(create,m) = create add(x,diff(m,n)) falls !isIn(x,n) diff(m,n) sonst diff(add(x,m),n) = Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-111 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge Signaturdiagramm: isIn create single T add,del Menge empty union, intersect diff true Bool false Hier mit Teilen des Signaturdiagramms von Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-112 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Mehrfachmengen: intuitiv: Mengen, in denen Elemente mehrfach vorkommen können zusätzliche Signatur: y isInTimes: T x Menge Æù //gibt an, wie oft Element //in Menge ist. Geändertes Axiom A5: y add(x,add(y,m))=add(y,add(x,m)) zusätzliche Axiome: y Aa: y Ab: isInTimes(x,create) = 0 1+isInTimes(x,m) falls x=y isInTimes(x,m) sonst isInTimes(x,add(y,m)) = Beispiel: Mehrfachmenge d. Primfaktoren von 2250 = [2, 3, 3, 5, 5, 5] Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-113 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Anmerkungen zur Implementierung Implementierung durch eine Liste y leicht, recht aufwändig Implementierung durch binären Suchbaum (nur Mengen) y nur es eine totale Ordnung ≤ auf den Elementen gibt Implementierung mit Bitvektoren (nur Mengen) y Wenn T endlich ist, kann für jedes Element aus T eine Position in einem Bitvektor festgelegt werden y Beispiel, T={a,b,c} à union(add(a,add(b,create)), add(c,create)) a b c union bitweises oder sehr schnelle Mengenoperationen a b c Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-114 M. Philippsen