Fachschaft Informatik Informatik 11 Kapitel 2 - Rekursive Datenstrukturen Michael Steinhuber König-Karlmann-Gymnasium Altötting 15. Januar 2016 Folie 1/77 Inhaltsverzeichnis I 1 2 3 4 5 6 7 8 Datenstruktur Schlange Warteschlange als Feld Warteschlange als Liste Die Methode ”einfuegen()” Die Methode ”informationenAusgeben()” Die Methode ”entfernen()” Trennung von Struktur und Inhalt Modellierungsaufgabe Datenstruktur Liste Entwurfsmuster Kompositum Datenstruktur Stapel Datenstruktur Schlange Die rekursive Datenstruktur Baum Folie 2/77 Inhaltsverzeichnis II Suchen in Binärbäumen Einfügen in Binärbäume Baum und Kompositum Baumdurchlauf Exkurs 1 - Knoten löschen Exkurs 2 - B-Baum 9 Die Datenstruktur Graph Eigenschaften von Graphen Adjazenzmatrix Breitensuche Tiefensuche Adjazenzliste Dijkstra-Alorithmus Folie 3/77 2.1 Datenstruktur Schlange Folie 4/77 2.1.1 Warteschlange als Feld Übung Warteschlange mit Datenstruktur Feld Implementiere eine Warteschlange mit Hilfe der Datenstruktur Feld, die die abgebildeten Attribute und Methoden besitzt. Folie 5/77 Nachteile dieser Implementierung • Die Warteschlange besitzt immer eine maximale Anzahl an Elementen (selbst bei sehr hoher Feldgröße). • Im Feld gibt es fast immer freie Plätze (Verschwendung von Speicherplatz). • Beim Entfernen von Elementen müssen die übrigen Elemente aufrücken (sehr umständlich). Folie 6/77 2.1.2 Warteschlange als Liste Objektdiagramm einer Warteschlange Folie 7/77 Klassendiagramm der Warteschlange Folie 8/77 Erweitertes Klassendiagramm der Warteschlange Folie 9/77 2.1.3 Die Methode ”einfuegen()” Folie 10/77 Folie 11/77 Folie 12/77 2.1.4 Die Methode ”informationenAusgeben()” Folie 13/77 2.1.5 Die Methode ”entfernen()” Folie 14/77 Folie 15/77 Folie 16/77 Kundenwarteschlange Plane eine Warteschlange Kunden. An welchen Stellen unserer Implementierung müssen wir Änderungen vornehmen? Probleme bei dieser Art der Implementierung • Die Klasse Patient hat zwei Aufgaben: • (A) Verwaltung der Daten (Patientenname) • (B) Verwaltung der Referenzen auf die Nachfolger • Dies stört bei der Wiederverwendung der WARTESCHLANGE für andere Zwecke (z.B. Druckaufträge). Lösung/Ziel ist es, die Aufgabe (B) in eine eigene Klasse KNOTEN auszulagern. Folie 17/77 2.2 Trennung von Struktur und Inhalt Objektdiagramm der Warteschlange Folie 18/77 2.2 Trennung von Struktur und Inhalt Klassendiagramm der Warteschlange Folie 19/77 2.2 Trennung von Struktur und Inhalt Probleme bei dieser Art der Implementierung • Die Klassen WARTESCHLANGE und KNOTEN müssen immer noch wissen, welche Elemente (der Typ der Elemente) sie verwalten. Folie 20/77 2.2 Trennung von Struktur und Inhalt Klassendiagramm der Warteschlange Folie 21/77 Warteschlange mit Java API import java . util . LinkedList ; public class WARTESCHLANGE { private LinkedList < DATENELEMENT > Warteschlange ; public WARTESCHLANGE () { Warteschlange = new LinkedList < DATENELEMENT >() ; } public void einfuegen ( DATENELEMENT n e u e s D a t e n e l e m e n t ) { Warteschlange . add ( n e u e s D a t e n e l e m e n t ) ; } public DATENELEMENT entfernen () { return Warteschlange . remove () ; } public void i n f o r m a t i o n e n A u s g e b e n () { for ( int i = 0; i < Warteschlange . size () ; i ++) { System . out . print ( Warteschlange . get ( i ) . i n f o r m a t i o n e n A u s g e b e n () + " " ); } System . out . println () ; } } Folie 22/77 2.3 Modellierungsaufgabe 1 1 Quelle: Abitur Informatik Bayern 2011 Folie 23/77 2.3 Modellierungsaufgabe 2 2 Quelle: Abitur Informatik Bayern 2011 Folie 24/77 2.3 Modellierungsaufgabe Folie 25/77 Erweiterte Anforderungen an die Datenstruktur Wir wollen unsere Datenstruktur erweitern: • Elemente sollen an bestimmten Stellen der Warteschlange angefügt und entfernt werden könnten. Dies gilt auch für ganz vorne. • Die Warteschlange soll Informationen darüber ausgeben, wie viele Knoten sie beinhaltet. • Es soll überprüft werden können, ob sich ein Datenelement in der Warteschlange befindet. Folie 26/77 2.4 Datenstruktur Liste Liste Da diese Anforderungen über die an eine Warteschlange hinausgehen, bezeichnen wir die Datenstruktur als einfach verkettete Liste. Folie 27/77 2.4 Datenstruktur Liste Operationen auf Zeichenketten Um Zeichenketten (und andere Objekte) miteinander vergleichen zu können gibt es verschiedene Methoden: • equals(vergleichswert):boolean: Gibt true zurück, falls Zeichenketten identisch, sonst false (Beispiel: variable.equals(”Test”);) • compareTo(vergleichswert):int: Gibt eine ganze Zahl zurück. Dabei entspricht bei [StringA] compareTo [StringB]: • =0: Beide Strings sind identisch. • <0: [StringA] kommt lexikographisch vor [StringB]. • >0: [StringB] kommt lexikographisch vor [StringA]. Folie 28/77 2.5 Entwurfsmuster Kompositum In fast allen Methoden der Klasse KNOTEN wird eine Fallunterscheidung bezüglich des Nachfolgers (für letzten Knoten) benötigt. Um diese zu umgehen, hat es sich bewährt, eine eigene Klasse ABSCHLUSS zu definieren, die kein Datenelement referenziert, sondern nur das Ende der Liste verwaltet. ABSCHLUSS und KNOTEN sind Unterklassen der Klasse LISTENELEMENT, welche nur die Signaturen der Methoden beinhaltet. Folie 29/77 2.5 Entwurfsmuster Kompositum Entwurfsmuster Kompositum Kompositum ist ein Entwurfsmuster (engl. Design Pattern) in der Softwareentwicklung. Diese Entwurfsmuster sind bewährte Lösungsschablonen für wiederkehrende Entwurfsprobleme. In allgemeiner Form sieht dieses Entwurfsmuster so aus: Folie 30/77 Folie 31/77 2.6 Datenstruktur Stapel Prinzip: Last in First out LiFo (oder wer zuletzt kommt, darf als erster gehen“) ” Folie 32/77 2.6 Datenstruktur Stapel Definition: Eine Datenstruktur heißt Stapel, wenn Elemente nur an einem Ende, der Stapelspitze (top), hinzugefügt oder entfernt werden können. Für Stapel sind die folgenden Operationen definiert: • Erzeugen eines leeren Stapels (init) • Hinzufügen eines Elements (push) • Prüfung, ob ein gegebener Stapel leer ist (isempty) • Inspizieren der Stapelspitze (top) • Entfernen der Stapelspitze (pop) Folie 33/77 2.6 Datenstruktur Stapel Anwendungen: Auswerten von Rechenausdrücken, syntaktische Analyse von Programmen, Bau von Übersetzern, Undo, Aufrufen von Unterprogrammen, Tiefensuche in Graphen,... Folie 34/77 2.7 Datenstruktur Schlange Prinzip: First in First out, FiFo (oder wer zuerst kommt, mahlt ” zuerst“) Folie 35/77 Datenstruktur Schlange Definition: Eine Datenstruktur heißt Schlange, wenn Elemente nur an einem Ende (dem Ende der Schlange) angefügt und nur am anderen Ende (dem Kopf der Schlange) entfernt werden können. Für Schlangen sind die folgenden fünf Operationen definiert: • Erzeugen einer neuen leeren Schlange (init) • Hintenanfügen eines Elements an eine gegebene Schlange (enqueue oder enter bzw. put) • Prüfung, ob die Schlange leer ist (isempty) • Inspizieren des Schlangenkopfes (front) • Entfernen des Schlangenkopfes (dequeue oder remove bzw. get) Folie 36/77 Datenstruktur Schlange Anwendungen: Druckaufträge (Druckerwarteschlange), Verwaltung von Prozessaufrufen im Betriebssystem, Hardwareschnittstellen zur seriellen Ein-/Ausgabe (Pufferspeicher z.B. Tastatur), ... Folie 37/77 2.8 Die rekursive Datenstruktur Baum Folie 38/77 2.8 Die rekursive Datenstruktur Baum Folie 38/77 2.8 Die rekursive Datenstruktur Baum Folie 38/77 2.8 Die rekursive Datenstruktur Baum Baum Aus einer einfach verketteten Liste entsteht ein Baum, indem die Knoten jeweils mehrere Nachfolger haben können und zusätzlich gilt: • Genau ein Knoten wird nicht von einem anderen Knoten referenziert. Diesen nennt man Wurzel des Baumes. • Alle anderen Knoten werden genau einmal referenziert. Man unterscheidet zwischen inneren Knoten und Blättern. Jeder Knoten lässt sich von der Wurzel aus auf genau einem Weg (über Kanten) erreichen. Ein spezieller Baum ist der Binärbaum. Dieser besitzt Knoten mit höchstens zwei Nachfolgern. Folie 39/77 2.8 Die rekursive Datenstruktur Baum Folie 40/77 2.8 Die rekursive Datenstruktur Baum Folie 41/77 2.8 Die rekursive Datenstruktur Baum Folie 42/77 2.8.1 Suchen in Binärbäumen Klasse BINBAUM public DATENELEMENT suchen ( String wert ) { if ( Wurzel != null ) return Wurzel . suchen ( wert ) ; else return null ; } Klasse KNOTEN public DATENELEMENT suchen ( String wert ) { if ( Daten . s c h l u e s s e l I s t G l e i c h ( wert ) ) return Daten ; else if ( Daten . s c h l u e s s e l I s t G r o e s s e r A l s ( wert ) ) { if ( L i n k e r N ac h f o l g e r != null ) return L i n k e r N a c h f o l g er . suchen ( wert ) ; else return null ; } else { if ( R e c h t e r N a c h f o l g e r != null ) return R e c h t e r N a c h f o l g e r . suchen ( wert ) ; else return null ; } } Folie 43/77 2.8.2 Einfügen in Binärbäume Klasse BINBAUM public void einfuegen ( DATENELEMENT daten ) { if ( Wurzel != null ) Wurzel . einfuegen ( daten ) ; else Wurzel = new KNOTEN ( daten ) ; } Klasse KNOTEN public void einfuegen ( DATENELEMENT daten ) { if ( Daten . istGleich ( daten ) ) {} else if ( Daten . i stGroess erAls ( daten ) ) { if ( L i n k e r N ac h f o l g e r != null ) L i n k e r N a c h f o l g e r . einfuegen ( daten ) ; else L i n k e r N a c h f o l g e r = new KNOTEN ( daten ) ; } else { if ( R e c h t e r N a c h f o l g e r != null ) R e c h t e r N a c h f o l g e r . einfuegen ( daten ) ; else R e c h t e r N a c h f o l g e r = new KNOTEN ( daten ) ; } } Folie 44/77 2.8.3 Baum und Kompositum Folie 45/77 2.8.3 Baum und Kompositum Folie 46/77 2.8.3 Baum und Kompositum Folie 47/77 Klasse BINBAUM 2.8.3 Baum und Kompositum public DATENELEMENT suchen ( String wert ) { return Wurzel . suchen ( wert ) ; } Klasse KNOTEN public DATENELEMENT suchen ( String wert ) { if ( Daten . s c h l u e s s e l I s t G l e i c h ( wert ) ) return Daten ; else if ( Daten . s c h l u e s s e l I s t G r o e s s e r A l s ( wert ) ) return L i n k er N a c h f o l g e r . suchen ( wert ) ; else return R e c h t e r N a c h f o l g e r . suchen ( wert ) ; } Klasse ABSCHLUSS public DATENELEMENT suchen ( String wert ) { return null ; } Folie 48/77 Klasse BINBAUM 2.8.3 Baum und Kompositum public void einfuegen ( DATENELEMENT daten ) { Wurzel = Wurzel . einfuegen ( daten ) ; } Klasse KNOTEN public void einfuegen ( DATENELEMENT daten ) { if ( Daten . istGleich ( daten ) ) {} else if ( Daten . i stGroess erAls ( daten ) ) L i n k e r N a c h f o l g er = L i n k e rN a c h f o l g e r . einfuegen ( daten ) ; else R e c h t e r N a c h f o l g e r = R e c h t e r N a c h f o l g e r . einfuegen ( daten ) ; } Klasse ABSCHLUSS public BAUMELEMENT einfuegen ( DATENELEMENT daten ) { return new KNOTEN ( daten ) ; } Folie 49/77 2.8.4 Baumdurchlauf Folie 50/77 2.8.4 Baumdurchlauf Definition Wenn man alle Elemente eines Baumes ausgeben möchte, muss man sich Strategien überlegen, in welcher Reihenfolge der Baum durchlaufen wird. Der Zugriff auf die einzelnen Knoten eines Baumes ist nur über die Wurzel möglich. Deshalb sind Algorithmen notwendig, die beim Durchlaufen eines Baumes jeden Knoten genau einmal besuchen und Informationen über dessen Datenelement ausgeben. Folgende drei (rekursive) Algorithmen leisten das Gewünschte: Folie 51/77 2.8.4 Baumdurchlauf inoder Baumdurchlauf inorder-Durchlauf (Reihenfolge: L K R ) • Beauftrage den linken Teilbaum des Knotens k mit inorder-Durchlauf • Besuche den Knoten k selbst • Beauftrage den rechten Teilbaum des Knotens k mit inorder-Durchlauf Beispiel: 1-3-4-5-7-8-9-10-14-15-17-18-19 Folie 52/77 Klasse BINBAUM 2.8.4 Baumdurchlauf (Implementierung) public void in or d er Au sg e be n () { Wurzel . i no rd e rA us ge b en () ; } Klasse KNOTEN public void in or d er Au sg e be n () { L i n k e r N a c h f o lg e r . i no rd e rA us ge b en () ; Daten . i n f o r m a t i o n A u s g e b e n () ; R e c h t e r N a c h f o l g e r . i no rd e rA us ge b en () ; } Klasse ABSCHLUSS public void in or d er Au sg e be n () { } Folie 53/77 2.8.4 Baumdurchlauf preorder Baumdurchlauf preorder-Durchlauf (Reihenfolge: K L R) • Besuche den Knoten k selbst • Beauftrage den linken Teilbaum des Knotens k mit preorder-Durchlauf • Beauftrage den rechten Teilbaum des Knotens k mit preorder-Durchlauf Beispiel: 9-5-3-1-4-7-8-17-14-10-15-18-19 Folie 54/77 2.8.4 Baumdurchlauf postorder Baumdurchlauf postorder-Durchlauf (Reihenfolge: L R K ) • Beauftrage den linken Teilbaum des Knotens k mit postorder-Durchlauf • Beauftrage den rechten Teilbaum des Knotens k mit postorder-Durchlauf • Besuche den Knoten k selbst Beispiel: 1-4-3-8-7-5-10-15-14-19-18-17-9 Folie 55/77 2.8.5 Exkurs 1 - Knoten löschen Vorgehen beim Löschen - 1 Es gibt drei Fälle, die beim Löschen eines Datenelements eintreten können: • Das DATENELEMENT wird von einem Knoten k referenziert, der keine Kinder hat (Nur Abschlüsse als Nachfolger): k wird gelöscht, ein beliebiger Nachfolger (ABSCHLUSS) wird zurückgegeben. Folie 56/77 2.8.5 Exkurs 1 - Knoten löschen Vorgehen beim Löschen - 2 • Das DATENELEMENT wird von einem Knoten k referenziert, der ein Kind hat: k wird durch das Kind ersetzt. Folie 57/77 2.8.5 Exkurs 1 - Knoten löschen Vorgehen beim Löschen - 3 • Das DATENELEMENT wird von einem Knoten k referenziert, der zwei Kinder hat: Dann bleibt Knoten k erhalten. Das DATENELEMENT in k wird durch das kleinste DATENELEMENT des rechten Teilbaums (bzw. größte DATENELEMENT des linken Teilbaums) von k ersetzt . Jedes dieser beiden DATENELEMENTe wird von einem Knoten referenziert, der höchstens ein Kind besitzt und daher wie in Fall 1 oder 2 entfernt werden kann. Folie 58/77 2.8.6 Exkurs 2 - B-Baum 3 3 Quelle: Haui/My Images: https://commons.wikimedia.org/wiki/File:B-tree-aggregated-example.png Folie 59/77 2.9 Die Datenstruktur Graph Folie 60/77 2.9.1 Eigenschaften von Graphen Unterschied Baum - Graph • Ein Knoten in einem Baum hat höchstens einen Vorgänger - in einem Graphen kann er mehr als einen haben. • In einem Baum gibt es keine Zyklen (Pfad, bei dem der Start- und Zielknoten identisch sind). • Ein Baum ist ein spezieller Graph. Folie 61/77 2.9.1 Eigenschaften von Graphen Definition Ein Graph G = (V , E ) besteht aus einer nichtleeren Menge von Knoten V und einer endlichen Menge von Kanten E . Eine Kante verbindet zwei Knoten. Folie 62/77 2.9.1 Eigenschaften von Graphen Definition Gerichtung • Bei gerichteten Graphen gibt es eine eindeutige Richtung der Kante von einem Startknoten zu einem Zielknoten. • Bei ungerichteten Graphen gilt die Verbindung für beide Richtungen. Folie 63/77 2.9.1 Eigenschaften von Graphen Definition Gewichtung • Bei einem gewichteten Graph wird jeder Kante ein Wert zugeordnet • Bei einem ungewichteten Graph besitzen die Kanten keine Werte. Folie 64/77 2.9.1 Eigenschaften von Graphen Definition Zusammenhängend 1 • Ungerichteter Graph: Ein ungerichteter Graph ist zusammenhängend, wenn von jedem Knoten zu jeden anderen Knoten mindestens ein Pfad existiert. Dieser Graph ist zusammenhängend. Ohne Kante zwischen A und D ist er nicht zusammenhängend! Folie 65/77 2.9.1 Eigenschaften von Graphen Definition Zusammenhängend 2 • Gerichteter Graph: Ein gerichteter Graph ist (stark) zusammenhängend, falls es von jedem Knoten aus einen gerichteten Weg zu jeden anderen Knoten im Graph gibt. Dieser Graph ist (stark) zusammenhängend. Ohne Kante zwischen E und C ist er nicht (stark) zusammenhängend! Da dieser Graph aber als ungerichteter Graph zusammenhängend wäre, ist er (schwach) zusammenhängend. Folie 66/77 2.9.1 Eigenschaften von Graphen Teiler Ein Graph hat die Zahlenwerte 1 bis 9 als Knoten. Über die Beziehung ist echter Teiler von“ sind diese gerichtet ” miteinander verbunden. 1 Wie viele Kanten gibt es? Zeichne den Graphen 2 Welcher Knoten muss entfernt werden, damit der Graph nicht mehr zusammenhängend ist? 3 Wie ändert sich der Graph, wenn die Beziehung ist ” Teiler von“ lautet? Folie 67/77 2.9.1 Eigenschaften von Graphen Klassendiagramm Folie 68/77 2.9.2 Adjazenzmatrix Definition Für die weitere Betrachtung von Algorithmen auf der Datenstruktur Graph bietet sich die “einfachere“ Umsetzung mittels Adjazenzmaritx an. Dabei werden die Kanteninformationen in der GRAPH-Klasse belassen und nur die Knoten-Informationen in der Klasse KNOTEN ausgelagert. In Java kann man die Kanteninformationen über ein zweidimensionales Feld definieren. Folie 69/77 2.9.2 Adjazenzmatrix nach von Folie 70/77 A B C D E F G A B C D 10 2 12 12 E F 5 8 3 8 10 2 5 8 G 6 6 3 8 12 12 2.9.2 Adjazenzmatrix nach von A B C D E F Folie 71/77 A B C D 9 3 E F 5 4 8 1 5 2 2.9.2 Adjazenzmatrix Klassendiagramm Folie 72/77 2.9.2 Adjazenzmatrix Folie 73/77 2.9.3 Breitensuche Siehe Folien - Breitensuche Warteschlange.pdf Folie 74/77 2.9.4 Tiefenensuche Siehe Folien - Tiefensuche Rekursiver Aufruf.pdf und Tiefensuche Stack.pdf Folie 75/77 2.9.5 Adjazenzliste Folie 76/77 2.9.6 Dijkstra-Alorithmus Siehe Folien - Dijkstra Prioritätswarteschlange.pdf Folie 77/77