Organisatorisches Statistik der Übungsblätter 1-3 Algorithmik 1 Prof. Dr. Michael Philippsen / Prof. Dr. Herbert Stoyan Holen Sie mehr aus sich raus! Toll! Super! Friedrich-Alexander-Universität Erlangen-Nürnberg Informatik 2/8 Programmiersysteme / Künstliche Intelligenz Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-2 Kapitel 10 - Abstrakte Datentypen 10.1 Einführung 10.1 10.2 10.3 10.4 10.5 10.6 10.7 Rückblick auf konkrete Datentypen (1) Einführung Programmentwicklung mit ADT Liste Keller Schlange Binärbaum Menge und Mehrfachmenge M. Philippsen 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. Handy aus! 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-3 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-4 M. Philippsen 10.1 Einführung 10.1 Einführung Rückblick auf konkrete Datentypen (2) Rolle von Typen in Software-Systemen 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 … Komponente 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 Komponente Komponente Verhalten ist nur durch Namen der Methoden angedeutet, eventuell im Kommentar. Es gibt bislang keine „saubere“ Spezifikation des Verhaltens! M. Philippsen Komponenten, die andere Komponenten nutzen, müssen sich auf die Erfüllung der Aufgaben verlassen können! Komponente Komponente Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-6 M. Philippsen 10.1 Einführung Komponente/Modul Rolle von Typen in Software-Systemen Dienst Algorithmen und Datenstrukturen à …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 Komponente Software-System 10.1 Einführung y löst logisch und funktional zusammenhängende Aufgabe y besitzt Schnittstelle bestehend aus Funktionssignaturen und Zusicherungen über diese Funktionen, so dass Kommunikation durch •Prozeduraufruf •Nachrichtenversand 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-8 M. Philippsen 10.1 Einführung 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 Signatur y Festlegung der auf dem Typ anwendbaren Operationen = Schnittstelle y Festlegung der Wirkung der Operationen 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: 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 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-9 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-10 M. Philippsen 10.1 Einführung 10.1 Einführung Axiome Weitere ADT-Begriffe (1) Axiome legen die Wirkung der Operationen fest, indem sie auf andere Funktionen zurückführen. 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 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. Vergleiche ADT-Konstruktoren mit Konstruktoren in Java. Rückführung auf die Wirkung anderer Funktionen Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-11 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-12 M. Philippsen 10.1 Einführung 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. 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-13 Die Wirkung von Folgen von Operationsaufrufen kann durch die Axiome auf die Normalform zurückgeführt werden. Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen //Anwendung A5 Normalform Algorithmik 1, WS 2004/05 Folie 10-14 M. Philippsen 10.2 Programmentwicklung mit ADT 10.2 Programmentwicklung mit ADT Beispiel: Einsatz eines ADTs bei der Programmentwicklung Datentyp Wörterbuch (Ew, Dw) Signatur: 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 y create: y enter: y find: Æ Wörterbuch Wörterbuch x Ew x Dw Æ Wörterbuch Wörterbuch x Ew Æ Dw c {?} y A2: 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 M. Philippsen create erschafft ein leeres Wörterbuch Axiome: y A1: 2 Konstruktoren, 1 Projektion 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 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 Nachdem die Wirkung der Operationen abstrakt festgelegt sind, kann man über die Implementierung nachdenken: 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: 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: à Das Wörterbuch hat die Länge 0 und die Form create à Nach A1 hat find(create,z) das gewünschte Resultat. à 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 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 à 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-17 M. Philippsen Kapitel 10 – Abstrakte Datentypen 10.1 √ Einführung 10.2 √ Programmentwicklung mit ADT y Implementierungsansatz 2: Algorithmik 1, WS 2004/05 Folie 10-18 = Datentyp zur Speicherung, Organisation, Verwaltung von Objekten eines Elementdatentyps Liste Keller Schlange Binärbaum Menge und Mehrfachmenge 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. y Typ der Elemente im Behälter ist Parameter des ADT y Behälterdatentypen sind sehr bedeutsam für die Praxis 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. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-19 M. Philippsen 10.3 Liste Im folgenden werden Behälterdatentypen als ADT formuliert. 10.3 10.4 10.5 10.6 10.7 Anzahl Vergleiche im ?-Fall 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-20 M. Philippsen 10.3 Liste 10.3 Liste append Gedanklich: Pfeilrichtung wird klar bei Implementierung tail neuestes Element Parameterlose Operation Signaturdiagramm: head head create Signatur Liste(T) y y y y y create: append: head: tail: length: Æ Liste Æ Liste ÆT Æ Liste Æù T x Liste Liste Liste Liste Konstruktoren T Projektion Hilfskonstruktor Projektion append tail 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) Liste head(create) und tail(create) sind nicht spezifiziert. Friedrich-Alexander-Universität Erlangen-Nürnberg 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-21 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-22 M. Philippsen 10.3 Liste 10.3 Liste Anmerkungen zur Normalform Anmerkungen zur Implementierung 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))) 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: 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). 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 y Einfügen, Löschen an beliebiger Stelle im Inneren der Liste y Verketten zweier Listen y Zugriff auf Anfangs-/End-/Teillisten Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-24 M. Philippsen 10.3 Liste 10.3 Liste Implementierungsbeispiel Implementierungsbeispiel „append“ Liste class Element { int datum; Element voriges; } class Liste { kopf Element neuestes Element Element kopf; Liste append(Element neu) {…} Element head() {…} Liste() {…} int length() {…} } voriges class Liste { ... Liste append(Element neu) { neu.voriges = kopf; kopf = neu; return this; } } kopf neu Element voriges voriges voriges voriges voriges voriges Verweis wird kopiert Beachte: Dies ist ein Implementierungsbeispiel. Später lernen wir bessere Implementierung kennen. Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-25 M. Philippsen 10.3 Liste Algorithmik 1, WS 2004/05 Folie 10-26 M. Philippsen 10.3 Liste Implementierungsbeispiel „head“ class Liste { ... Element head() { return kopf; } } Implementierungsbeispiel „tail“ Liste kopf Element voriges Ein Verweis auf diese zuletzt eingefügte Listenelement wird geliefert. class Liste { ... Liste tail() { if (kopf != null) kopf = kopf.voriges; return this; } } voriges Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen kopf Element voriges voriges tail ist auf leerer Liste nicht definiert. Schutzabfrage. Später besser. Friedrich-Alexander-Universität Erlangen-Nürnberg Liste voriges voriges Algorithmik 1, WS 2004/05 Folie 10-27 Liste Algorithmik 1, WS 2004/05 Folie 10-28 Der Speicherbereiniger entfernt den früheren Listenkopf (irgendwann) M. Philippsen 10.3 Liste 10.3 Liste Implementierungsbeispiel „length“ Implementierungsbeispiel „length“ Liste 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); } } } kopf Element 1+… 3 voriges 2 voriges 1+… 1 1+… voriges class Liste { ... //entrekursivierte Fassung int length() { int len = 0; Element e = kopf; while (e != null) { e = e.voriges; len += 1; } return len; } } kopf Element 0, e voriges 1, e voriges 2, e voriges 3, e 0 Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-29 M. Philippsen 10.3 Liste 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; } } Implementierungsbeispiel „reverse“ - Fehlersuche (1) Liste Liste kopf Element voriges voriges voriges 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; } Was ist hier falsch? kopf Element voriges voriges voriges neueListe kopf Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-31 Liste Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-32 M. Philippsen 10.3 Liste 10.3 Liste Implementierungsbeispiel „reverse“ - Fehlersuche (2) Implementierungsbeispiel „reverse“ - korrigiert 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; } Liste kopf Element voriges verwaist: voriges 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 neueListe kopf voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-33 Algorithmik 1, WS 2004/05 Folie 10-34 M. Philippsen M. Philippsen 10.3 Liste 10.3 Liste Orthogonale Liste (1) Orthogonale Liste (2) Listenelemente gleichzeitig in mehreren Listen führen. Beispiel: dünnbesetzte Matrix Spaltenköpfe Listenelemente gleichzeitig in mehreren Listen führen. Beispiel: dünnbesetzte Matrix … 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 Spaltenköpfe … 1.0 2.3 1.0 2.3 2.5 1.3 4.1 5.7 Zeilenköpfe 2.3 2.5 0 0 Zeilenköpfe 1.0 0 1.3 0 … 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-35 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-36 M. Philippsen 10.3 Liste 10.4 Keller/Stapel („stack“) Übliche Erweiterungen des bisherigen ADT Liste Gedanklich 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 Entfernte Elemente 4. Eingefügte Elemente 4. 3. 2. 1. Konzept des Positionszeigers, der auf ein Element der Liste zeigt. 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. Keller Das zuletzt eingefügte Element kommt als 1. heraus. 4. • Letzter-Zuerst-Strategie („last in first out“, LIFO) • Wenden eines Zugs über ein Abstellgleis 3. 2. 1. Auslesen liefert das zuletzt eingefügte Element. Entfernen entfernt das zuletzt eingefügte Element. Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-37 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-38 M. Philippsen 10.4 Keller/Stapel („stack“) 10.4 Keller/Stapel („stack“) Signatur Keller(T) Signaturdiagramm: y y y y y create: push: pop: top: empty: T x Keller Keller Keller Keller Æ Keller Æ Keller Æ Keller ÆT Æ Boolean top Axiome für LIFOVerhalten T 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 push Ebenso wie tail eine verkürzte Liste zurück gibt, liefert pop einen Keller ohne das oberste Element. Keller empty true Bool pop false Normalform: nur create und push sind Konstruktoren. LIFO-Eigenschaft mit vollständiger Induktion beweisbar. Hier mit Teilen des Signaturdiagramms von Boolean Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-39 create Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-40 M. Philippsen 10.4 Keller/Stapel („stack“) 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. 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) Beispiel: top(push(x,s)) = top(append(x,s)) = x //Nachweis der Keller-Eigenschaften trivial Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-41 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-42 M. Philippsen 10.4 Keller/Stapel („stack“) 10.4 Keller/Stapel („stack“) Keller zur Implementierung geschachtelter Methodenaufrufe Keller zur Auswertung arithmetischer Ausdrücke in Postfixform Für jeden Methodenaufruf wird eine Methodenschachtel angelegt. Schachteln werden nach LIFO-Strategie wieder freigegeben. Arithmetischer Ausdruck: 5 * (7 - 3) Postfixform: 573-* Ablauf: m() { ... n(); ... } m()-Aufruf n() { ... o(); ... } n()-Aufruf m n m Rücksprungadresse o()-Aufruf Keller der MethodenSchachteln bis zum o Aufruf von o. 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 n m Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-43 y y y y Kellermaschine Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen 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“) 10.4 Keller/Stapel („stack“) Fakultätsfunktion mit expliziter Kellerung Anmerkung zur Implementierung 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) push 3 push 2 4 3 4 2 3 4 top,pop erg = 2 top,pop erg = 6 3 4 top,pop erg = 24 10.5 Schlange/Warteschlange („queue“) Erster-Zuerst-Strategie („first in first out“, FIFO) dequeue Wegnehmen des ältesten Elements Signatur Schlange(T) E Algorithmik 1, WS 2004/05 Folie 10-46 M. Philippsen Beispiel Schlange Aufbau einer Schlange 1 create enq(1,… Arbeiten auf der Schlange Æ Schlange Æ Schlange ÆT Æ Schlange Æ Boolean 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-47 n y enq(2,enq(1,create)) 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. T x Schlange Schlange Schlange Schlange pop 0 10.5 Schlange/Warteschlange („queue“) Kopf enqueue Hinzufügen des neuesten Elements SP SP M. Philippsen Ende push E Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-45 create: enq: front: deq: empty: n 4 Friedrich-Alexander-Universität Erlangen-Nürnberg y y y y y 0 while (!keller.empty()) ergebnis *= keller.topAndPop(); push 4 Gedanklich 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: Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-48 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Axiome y A1: deq(enq(x,q)) = q falls empty(q) enq(x,deq(q)) sonst Normalform: nur create und enq sind Konstruktoren. FIFO-Eigenschaft per vollständiger Induktion beweisbar. 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 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-49 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-50 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Signaturdiagramm: Schlangenimplementierung mit einer Liste (1) 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 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-52 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Schlangenimplementierung mit einer Liste (2) Schlangen werden zur Abarbeitung von Aufträgen in Eingangsreihenfolge verwendet: append(x,createListe) y y y y y y falls empty(q) enq(x,q) = append(y,enq(x,l)) falls q=append(y,l) Beispiel: enq(2,enq(1,createSchlange)) append(1,createListe) enq(2, 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 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-53 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Schlange Schlangen werden mit zusätzlichem Zeiger auf das Schlusselement implementiert. Leere Schlange: kopf=ende=null kopf ende Anmerkung zur Implementierung (2) Element voriges voriges voriges 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. voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-55 Algorithmik 1, WS 2004/05 Folie 10-54 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Anmerkung zur Implementierung (1) 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. Prozessverwaltung im Betriebssystem Speicherverwaltung Druckaufträge Kommunikationssoftware Tastaturpuffer … Schlange kopf ende Element voriges voriges voriges Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-56 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Ähnlich wie beim Keller kann auch eine Reihung/ein Speicherbereich zur Schlangenimplementierungen verwendet werden: „Zirkuläre Reihung“ 0 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 n F enq E kopf ende 0 n F deq E E ende kopf kopf 0 n E kopf Friedrich-Alexander-Universität Erlangen-Nürnberg ende Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-57 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-58 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Prioritätswarteschlange („priority queue“) Beispiel Prioritätswarteschlange 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: Aufbau einer Prioritätswarteschlange 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 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 Æ Schlange Æ Schlange ÆTxù Æ Schlange Æ Boolean y front(deq(…siehe oben…)) front x3 b2 v3 a2 = (x,3) Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-59 y enq((x,3),enq((b,2),enq((v,3),enq((a,2),create)))) front x3 b2 a2 deq(… Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-60 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Prioritätswarteschlange („priority queue“) Axiom der Schlange Zusätzlich erforderliche Operation: y A1: Æù 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! 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 Zugehöriges Axiom: y A5: maxprio(enq((x,g),q) = g g maxprio(q) falls empty(q) falls maxprio(q)<g sonst 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 Paar (Element, Priorität) Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-61 M. Philippsen 10.5 Schlange/Warteschlange („queue“) Implementierung einer Prioritätswarteschlange mit einer Liste x falls empty(q) front(q) sonst Jetzt: Einfügen sortiert nach Priorität, keine Hilfsoperation maxprio front(enq(x,q)) = Abbildung: 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: M. Philippsen 10.5 Schlange/Warteschlange („queue“) Axiom der Schlange y A2: Algorithmik 1, WS 2004/05 Folie 10-62 (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 Falls (x,g) höchste Priorität hat, einfach y createSchlange = createListe an Liste anhängen y deq(append((x,g),q)) = q y front(append((x,g),q)) = (x,g) append((x,g),createListe) falls empty(q) y enq((x,g),q) = append((x,g),q) falls front(q).gewicht<g append(y,enq((x,g),l)) sonst, mit q=append(y,l) y empty(create) = true Sonst Listenkopf y empty(append((x,g),s)) = false ü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-63 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-64 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung Anmerkungen zur Implementierung (2) Einsetzen eines Elements in eine Warteschlange Einsetzen eines Elements in eine Warteschlange y Leere Schlange y Nicht-leere Schlange kopf ende à in der Mitte kopf ende voriges voriges kopf ende y Nicht-leere Schlange voriges voriges voriges à als neuen Kopf voriges kopf ende voriges voriges voriges Das Einsetzen erfolgt immer nach einem vorhandenen Element. à am Ende kopf ende Friedrich-Alexander-Universität Erlangen-Nürnberg voriges voriges M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-66 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Schleppzeiger (1) Schleppzeiger (2) 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. 85 (neu) voriges 100 voriges 90 voriges 80 voriges 90<85? Æ Benutze Verweis, der stets um ein Element hinter Lauf-Verweis zurück ist 100 voriges 90 voriges 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 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 100<85? voriges Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-65 kopf ende voriges 85 (neu) voriges 100<85? SL SL 90<85? SL 80<85? Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-68 M. Philippsen 10.5 Schlange/Warteschlange („queue“) 10.5 Schlange/Warteschlange („queue“) Anmerkungen zur Implementierung (3) Anmerkungen zur Implementierung (4) Entfernen eines Elements aus einer nicht-leeren Warteschlange Entfernen eines Elements aus einer nicht-leeren Warteschlange y am Anfang kopf ende y in der Mitte kopieren voriges voriges kopf ende 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. kopieren y am Ende kopf ende voriges voriges voriges kopieren voriges voriges voriges Schleppzeiger ist notwendig Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-69 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-70 10.5 Schlange/Warteschlange („queue“) Kapitel 10 – Abstrakte Datentypen Doppelte Verkettung 10.1 √ Einführung 10.2 √ Programmentwicklung mit ADT 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 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-72 M. Philippsen 17.1 Graph-Grundlagen 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: Bei gerichteten Graphen ist ein Baum ein Wurzelgraph, in dem zu jedem Knoten genau ein (eindeutiger) Pfad von der Wurzel aus führt. 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. Wurzel X Wurzelgraph: DAG: Wurzel Baum: X Es gibt noch andere Möglichkeiten, um durch Entfernen von Kanten aus dem Graph ein Baum zu machen. X Ein DAG mit mehreren Wurzeln, aber eindeutigen Pfaden, heißt Wald. Wurzel nur zyklenfrei, wenn X entfernt ist. Friedrich-Alexander-Universität Erlangen-Nürnberg Wurzel Algorithmik 1, WS 2004/05, Vorgriffssfolie Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05, Vorgriffssfolie 17.1 Graph-Grundlagen 17.1 Graph-Grundlagen Aus dieser Baum-Definition folgt: Weitere Baum-Begriffe (1) 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 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 M. Philippsen Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen 17.1 Graph-Grundlagen Weitere Baum-Begriffe (2) Am Beispiel: innerer Knoten Der Unterbaum eines Knotens v im Baum sind v und alle nachfolgenden Knoten plus die verbindenden Kanten. y Unterbäume sind wieder Bäume. 1:2 0:1 Triviale Bäume: leerer Graph; kantenloser Graph mit nur einem Knoten. Wurzel Die Länge des Pfades von der Wurzel zu einem Knoten k bestimmt die Höhe von k im Baum. 2:0 4:0 Blatt 3:1 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. Blatt 2:1 n:m = Höhe:Grad Unterbaum dieses Knotens: 0:1 2:0 Grad des Baums: 2 1:1 Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 17.1 Graph-Grundlagen 17.1 Graph-Grundlagen Beispiele: Andere Darstellungsformen von Bäumen Kontour-Darstellung ▪ Einrückungsdarstellung Ausdrucksbaum „Kantorowitsch-Baum“ 5 * (7-3) B H Elisabeth 3 Victoria Loius Alice Olga Georg I Andrew J D B Elisabeth II Mary Georg VI George V 7 A Cecilia Claude * 5 Abstammungsbaum A F C E Charles Philip H J G C D E G F Listendarstellung A(B(HJ)C( DE( G)F )) ist Kind von Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05, Vorgriffssfolie Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05, Vorgriffssfolie M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Signatur BinBaum(T) Beispiel Binärbaum y y y y y y create: bin: left: right: value: empty: Æ BinBaum Æ BinBaum Æ BinBaum Æ BinBaum ÆT Æ Boolean BinBaum x T x BinBaum BinBaum BinBaum BinBaum BinBaum Hilfefunktion: value(left(bin(leaf(3),2,leaf(4)))) leaf(3) A1: A2: A3: A4: A5: leaf(4) 3 Axiome: y y y y y leaf v = bin(create,v,create) //erzeuge Blatt 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 =3 2 bin(..2..) 3 4 3 4 empty(left(left(…obiger Baum…)) 2 3 Friedrich-Alexander-Universität Erlangen-Nürnberg left(..) 4 left(..) 3 = true left(..) Die „leeren Nachfolger“ der Blätter zählen bei der Baumhöhe nicht mit. 3 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-81 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-82 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Signaturdiagramm: Anmerkungen zur Implementierung (1) Explizite Darstellung mit Verweisen value T bin create BinTree empty true y Verweise von Knoten zu Nachfolgern/Kindern/Söhnen Reihung von Verweisen, maximaler Knotengrad legt Länge der Reihung fest. Binärbaum: 2 Bool y Verweise auf Vorgänger/Elternknoten/Vater left,right Allgemeine Bäume: bei stark schwankendem Grad, kann ggf. Liste mit Verweisen günstiger sein. 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 y beide Sorten von Verweisen Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-84 Kanten im Baum M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Anmerkungen zur Implementierung/beliebiger Grad (2) Anmerkung zur Implementierung (3) Explizite Darstellung mit Verweisen Mit Reihungen und Indizes, ohne explizite Verweise y Mit maximal 2 Verweisen: Ein Knoten zeigt nur auf einen Nachfolger, der dann die Geschwisterknoten verkettet nicht sinnvoll für Binärbäume A B D A B C D E F G 0 1 2 3 4 5 6 zugeordneter Index C E F 1 2 G 3 -1 -1 5 -1 -1 Index linkes Kind 4 -1 -1 6 -1 -1 Index rechtes Kind für allgemeine Bäume: mehr Zeilen zeigt auf Geschwisterknoten zeigt auf Kind Friedrich-Alexander-Universität Erlangen-Nürnberg -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-85 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-86 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Anmerkungen zur Implementierung (4) Haldenspeicherung Implizite Darstellung: 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.) 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 Nachfolge von A[1] 6 7 A B C D E F G C E F 2 anderer Faktor für allgemeine Bäume A[1] A[2] A[3] A[4] … A[k] … A[n] 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 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-88 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Entnahme aus der Halde Entnahme aus der Halde am Beispiel (1) Der Knoten (mit höchster Priorität) wird vorne aus der Halde entfernt. 1 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. 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 ≥ 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 2 6 7 3 M. Philippsen 2 … M. Philippsen Entnahme aus der Halde am Beispiel (2) Entnahme aus der Halde am Beispiel (3) 16 < > 13 > < 6 5 7 3 < > < 2 4 11 13 > < 12 9 > > 15 > < 10 1 < 15 > 1 4 Algorithmik 1, WS 2004/05 Folie 10-90 10.6 Binärbaum < 8 Erfüllt die Haldeneigenschaft 3 10.6 Binärbaum 14 11 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-89 < 4 5 7 9≥ 9≥ 2 14 > 8 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 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-92 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Entnahme aus der Halde am Beispiel (4) Entnahme aus der Halde am Beispiel (5) 15 < > 1 13 > < 14 < > < 6 5 7 3 < > < 2 4 11 13 > < 12 9 > > 14 > < 10 15 < 1 > 8 Friedrich-Alexander-Universität Erlangen-Nürnberg 10 < > < 6 5 7 M. Philippsen > 3 < > < 2 4 11 Algorithmik 1, WS 2004/05 Folie 10-94 10.6 Binärbaum Entnahme aus der Halde am Beispiel (6) Entnahme aus der Halde am Beispiel (7) 15 < 13 > < 1 5 7 > < 10 > 12 9 > 3 6 7 8 9 10 11 12 13 14 15 16 16 15 13 14 10 9 12 6 5 < > < 2 4 11 > 2 3 4 7 3 2 4 11 8 1 1 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 15 1 9 12 6 5 7 3 2 4 11 8 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 8 Maximalelement wieder vorne. Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-95 8 5 1 > 14 < > M. Philippsen 10.6 Binärbaum 6 12 9 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-93 < > < Erfüllt die Haldeneigenschaft Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-96 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Einfügen in eine Halde Einfügen in die Halde am Beispiel (1) Einfügen hat ähnliche Grundidee, wie Entfernen Neues Element wird als A[k+1] in die Halde geschrieben. 15 < 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. > 14 13 > < 6 Im schlimmsten Fall sind log2k Vergleiche nötig, bis die Haldeneigenschaft wieder erfüllt ist. 10 < > < 1 5 7 > < 12 9 > 3 < > < 2 4 11 > 8 16 Friedrich-Alexander-Universität Erlangen-Nürnberg Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-97 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-98 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Einfügen in die Halde am Beispiel (2) Einfügen in die Halde am Beispiel (1) 16 < 1 > 15 13 > < 14 < 6 10 > 5 < 7 > < 12 9 > 3 < 2 > 4 < 11 > 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 7 3 2 4 11 8 1 6 5 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 8 < Maximalelement wieder vorne. 1 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-99 Erfüllt die Haldeneigenschaft Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-100 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Binärer Suchbaum Signatur SuchBaum(T), T mit Ordnungsrelation: y y y y = 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 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-101 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-102 M. Philippsen 10.6 Binärbaum 10.6 Binärbaum Zusätzliche Axiome von SuchBaum(T): Suchbäume sehen je nach Einfügereihenfolge anders aus insert(3,insert(5,insert(2,insert(4,create)))) 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)) = 4 falls x=v falls x<v falls x>v 2 5 3 insert(5,insert(3,insert(4,insert(2,create)))) true find(x,b1) find(x,b2) falls x=v falls x<v falls x>v 2 4 3 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-103 Wurzel 5 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-104 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Mengen sind einer der am häufigsten vorkommenden ADT Es gibt zahlreiche Implementierungsmöglichkeiten Beispiel Menge: 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 Mengen haben keine Duplikate add(a,add(a,add(b,create))) b add(a add(b 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 Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-105 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-106 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Axiome Alternative mit weiteren Operationen y A1: y A2: isIn(x,create) = false 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)) = y A3: y A4: empty(create) = true empty(add(x,m)) = false y A5: add(x,add(y,m)) = y A6: del(x,create) = create y A7: true del(x,add(y,m)) = Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-107 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 M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-108 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Beispiel erweiterter ADT Menge: Axiome zu den alternativen Signaturen (1) y A1-A4 bleiben unverändert (isIn, empty) union(add(a,add(b,create)), add(c,create)) b add(a add(b a b union c b a c add(c 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: union(m,n) falls isIn(x,n) add(x,union(m,n)) sonst union(add(x,m),n) = y A10: intersect(create,m) = create add(x, intersect(m,n)) intersect(add(x,m),n) = intersect(m,n) y A11: Friedrich-Alexander-Universität Erlangen-Nürnberg „schlankere“ Axiome M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-110 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) 10.7 Menge („set“) und Mehrfachmenge Axiome zu den alternativen Signaturen (2) Signaturdiagramm: y A13: sonst Friedrich-Alexander-Universität Erlangen-Nürnberg Algorithmik 1, WS 2004/05 Folie 10-109 y A12: falls isIn(x,n) isIn diff(create,m) = create add(x,diff(m,n)) falls !isIn(x,n) diff(m,n) sonst create single diff(add(x,m),n) = 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-111 Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-112 M. Philippsen 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) 10.7 Menge („set“) und Mehrfachmenge („multiset, bag“) Mehrfachmengen: Anmerkungen zur Implementierung intuitiv: Mengen, in denen Elemente mehrfach vorkommen können Implementierung durch eine Liste y leicht, recht aufwändig zusätzliche Signatur: y isInTimes: T x Menge Æù //gibt an, wie oft Element //in Menge ist. Geändertes Axiom A5: zusätzliche Axiome: y Ab: 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} y add(x,add(y,m))=add(y,add(x,m)) y Aa: Implementierung durch binären Suchbaum (nur Mengen) isInTimes(x,create) = 0 1+isInTimes(x,m) falls x=y isInTimes(x,m) sonst isInTimes(x,add(y,m)) = à union(add(a,add(b,create)), add(c,create)) a b c union bitweises oder 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 sehr schnelle Mengenoperationen a b c Friedrich-Alexander-Universität Erlangen-Nürnberg M. Philippsen Algorithmik 1, WS 2004/05 Folie 10-114 M. Philippsen