Modul: Programmierung B-PRG Grundlagen der Programmierung 1 – Teil 1 – V10 Graphen, Bäume, Halden Prof. Dr. Detlef Krömker Professur für Graphische Datenverarbeitung Institut für Informatik Fachbereich Informatik und Mathematik (12) Hier wird Wissen Wirklichkeit Übersicht: Wichtige Datenstrukturen lineare Strukturen nichtlineare Strukturen nicht geordnete Strukturen geordnete Strukturen string tupel frozenset Liste Stapel Schlange list stack fir queue Graph gerichtet Menge Abbildung set dictionary Verbund ··· azyklisch Feld array 2 Baum Vorrangschlange priority queue Programmieren 1 – Teil 1 – V10 WS 2007/2008 Die „Brot und Butter“ Datenstruktur Baum kennen lernen. Hier wird Wissen Wirklichkeit Graph gerichtet azyklisch ··· Baum Eine spezielle Klasse „Baum“ realisieren. tree Einordnung und Spezialisierung des Datentyps Baum kennenlernen. binary tree Programmieren 1 – Teil 1 – V10 WS 2007/2008 Union ··· Prof. Dr. Detlef Krömker Unser heutiges Lernziel 3 Record tree Prof. Dr. Detlef Krömker M-Way quadtree Suchbaum Halde search tree heap ··· octtree B-Tree Hier wird Wissen Wirklichkeit 1 Nicht nur eine „Erfindung“ der Informatik Stammbaum des Wissens Band 1 der Encyclopédie ou Dictionnaire raisonné des sciences, des arts et des métiers (28 Bände, vollendet im Jahr 1772) Jean Baptiste le Rond d'Alembert und Denis Diderot Programmieren 1 – Teil 1 – V10 WS 2007/2008 4 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Wo sind wir in Teil1? V 0 ---V 1 V 2 V 3 ---V 4 V 5 ---V 6 V 7 ---V 8 V 9 V10 V11 5 Begrüßung und Einführung Daten – Information – Wissen Computer – Algorithmus – Programm Variablen – Datentypen – Objekte Elementare numerische Datentypen Zeichenketten Verzweigungen und Schleifen Prozeduren Aggregierte Datentypen Klassen Graphen und Bäume Bibliotheken Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Übersicht ‣ Graph Kategorisierung von Graphen Graphen als Datenstruktur Adjazenzmatrix Adjazenzliste Inzidenzmatrix Implementierung von Graphen in Python ‣ Baum Implementierung von Bäumen ‣ Heap ‣ Zusammenfassung 6 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 2 1 5 5 661 2 661 3 1 2 4 3 17 4 17 5 Graph 5 5 7 8 661 7 8 66 20 19 18 9 66 19 18 66 18 20 21 66 18 32 66 648 14 19 66 32 13 13 648 9 648 21 19 14 648 20 15 5 15 21 16 20 21 16 661 17 52 22 50 49 3 51 3 5 22 50 49 17 50 3 52 3 661 18 661 18 5 7 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Graph – Definition (Graphentheorie) Ein Graph G ist ein geordnetes Paar zweier Mengen: G = (V, E) Dabei bezeichnet V die Menge der im Graph enthaltenen Knoten (Vertex) und E die Menge der Kanten (Edge) des Graphen. Anschaulich ist ein Graph ein Gebilde aus Knoten (auch Ecken oder Punkte), die durch Kanten verbunden sein können. Knoten 1 1 2 Kante 3 Achtung: verschiedene Bilder können denselben Graphen darstellen. 2 4 3 4 Im Beispiel sind die Knoten mit den Ziffern 1..4 benannt. 8 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Kategorisierung von Graphen ungerichtete Graphen ohne Mehrfachkanten: E ist eine Teilmenge aller 2-elementigen Teilmengen von V schlicht oder einfach e gerichtete Graphen ohne Mehrfachkanten: E ist eine Teilmenge des kartesischen Produktes V x V 9 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Startknoten von e Digraph (Directed Graph). Endknoten von e Hier wird Wissen Wirklichkeit 3 Kategorisierung von Graphen (Eigenschaften von E) ungerichteten Graphen mit Mehrfachkanten: E ist eine Multimenge [Elemente können mehrfach vorkommen] über der Menge aller 2-elementigen Teilmengen von V gerichteten Graphen mit Mehrfachkanten: E ist eine Multimenge über dem kartesischen Produkt V x V (Multigraph) (Multigraph) Hypergraphen eine Teilmenge der Potenzmenge von V. 10 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Eigenschaften von Graphen Hat eine Kante e in gerichteten Graphen die Form (v, v), so spricht man von einer Schleife. Ein Graph, bei dem dieses nie vorkommt, nennt man schleifenfrei. Hier gibt es viel mehr zu lernen, siehe Algorithmen und Datenstrukturen und … 11 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Graphen als Datenstruktur Ein Graph als Datentyp sollte mindestens die folgenden Operationen haben ‣ Einfügen (Kante, Knoten) ‣ Löschen (Kante, Knoten) ‣ Finden eines Objekts (Kante, Knoten). Die bekanntesten Repräsentation von Graphen im Computer sind ‣ die Adjazenzmatrix (Nachbarschaftsmatrix) ‣ die Adjazenzliste (Nachbarschaftsliste) ‣ die Inzidenzmatrix (Knoten-Kanten-Matrix, seltener genutzt) 12 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 4 Adjazenzmatrix Ein Graph mit n Knoten kann durch eine n×n-Matrix repräsentiert werden. Dazu nummeriert man die Knoten von 1 bis n durch und trägt in die Matrix die Beziehungen der Knoten zueinander ein. 1 1 2 3 1 1 1 2 1 2 1 3 4 4 3 1 4 1 Hypergraphen lassen sich nicht durch eine Adjazenzmatrix darstellen. Wenn man anstelle der 1 z.B. einen Integerwert zulässt, so können die Kanten „Gewichte“ haben oder „gefärbt“ sein. 13 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Adjazenzliste Die Adjazenzliste wird in ihrer einfachsten Form durch eine einfach verkettete Liste aller Knoten des Graphen dargestellt, wobei ‣ jeder Knoten eine Liste aller seiner Nachbarn (in ungerichteten Graphen) bzw. ‣ Nachfolger in gerichteten Graphen besitzt. Vielfachheiten der Kanten Knotengewichte, und Kantengewichte werden meist in Attributen der einzelnen Elemente gespeichert. 14 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Beispiel Adjazenzliste 1 [1,2,3] 2 [3] 3 [4] 4 [1] 1 2 3 4 Direkte Umsetzung in Python könnte man also verschachtelte Listen implementieren: (Knoten-) Listen von (Kanten-) Listen: Ist einfach, wenn die Knoten wie oben nummeriert sind: Einfügen-Kante Î Kantenliste.append Einfügen-Knoten: prüfen, ob schon vorhanden, sonst Knotenliste.append Löschen Kante Î indexiert auf Liste zugreifen und Kantenliste.remove Löschen Knoten Î Knoten selbst löschen: Knotenliste.remove, dann aber auch alle Verweise auf diesen Knoten löschen … etwas aufwendiger, geht aber … wie? Nachteile? 15 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 5 Adjazenzliste (2) ‣ In der Praxis verwendet man meist diese Form der Repräsentation. ‣ aufwändiger zu implementieren und zu verwalten (zumindest in vielen Programmiersprachen), bieten aber eine Reihe von Vorteilen gegenüber Adjazenzmatrizen. ‣ verbrauchen nur linear viel Speicherplatz, was insbesondere bei dünnen Graphen (also Graphen mit wenig Kanten) von Vorteil ist, während die Adjazenzmatrix quadratischen Platzbedarf bezüglich der Anzahl Knoten besitzt (dafür aber kompakter bei dichten Graphen, also Graphen mit vielen Kanten ist). ‣ 16 Zum anderen lassen sich viele graphentheoretische Probleme nur mit Adjazenzlisten in linearer Zeit lösen. … das behandeln Sie noch intensiv in Algorithmentheorie Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Ein Beispiel in Python: Initialisierung Wir wollen nebenstehenden Graph in Python als Dictionary repräsentieren, aber allgemeiner, mit nebenstehender Knotenbezeichnung Vorteile: • beliebige Bezeichnungen der Knoten möglich • Datentyp Dictionary sichert Eindeutigkeit der Knoten A B C D >>> Adjazenzliste = {"A":["A","B","C"],"B":["C"],"C":["D"],"D":["A"]} >>> Adjazenzliste {'A': ['A', 'B', 'C'], 'C': ['D'], 'B': ['C'], 'D': ['A']} >>> 17 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Ein paar Operationen auf der Adjazenzliste >>> Adjazenzliste.update ({"E":["A"]}) >>> Adjazenzliste {'A': ['A', 'B', 'C'], 'C': ['D'], 'B': ['C'], 'E': ['A'], 'D': ['A']} >>> k=Adjazenzliste.get ("C") >>> k ['D'] >>> k.append ("E") >>> Adjazenzliste.update ({"C":k}) >>> Adjazenzliste {'A': ['A', 'B', 'C'], 'C': ['D', 'E'], 'B': ['C'], 'E': ['A'], 'D': ['A']} 18 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker A B E C D Hier wird Wissen Wirklichkeit 6 Weitere Operationen – hier einmal mit einer Exception programmiert >>> Adjazenzliste.pop ("C") ['D', 'E'] >>> Adjazenzliste {'A': ['A', 'B', 'C'], 'B': ['C'], 'E': ['A'], 'D': ['A'] A A B B E E C D D Problem: Zwei Kanten verweisen ins „Nichts“ … den Knoten C gibt es nicht mehr Programmieren 1 – Teil 1 – V10 WS 2007/2008 19 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Zwischenruf: Eine interessante Programmiermethodik - Ausnahmen (Exceptions) Python unterstützt die Programmierung mit Exceptions. Exceptions werden während des Programmlaufs generiert (raised) deuten meist auf Fehler hin und führen zum Abbruch des normalen Kontrollflusses eines Programmes. Eine Ausnahme wird mit der raise-Anweisung ausgelöst. Das allgemeine Format einer raise-Anweisung ist raise Exception [, value], wobei Exception der Ausnahme-Typ und value ein optionaler Wert mit spezifischen Details über die Ausnahme ist, z.B.: raise RuntimeError, 'Fataler Fehler' 20 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Zwischenruf: Ausnahmen (Exceptions) – Beispiele eingebauter Typen Exeption die Superklasse aller Exceptions ArithmeticError die Superklasse für OverflowError, ZeroDivisionError und FloatingPointError LookupError die Superklasse von IndexError und KeyError TypeError ValueError Typfehler, z.B. bei falscher Zuweisung Argumentfehler, die kein TypeError sind usw. 21 viele mehr Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 7 Das Programmieren mit Exceptions Um eine Ausnahme abzufangen (catch exeptions), verwendet man die try- und exceptAnweisungen try: suite [except [ExeptionName [, data]]: suite … [else: suite] [finally: suite] # der zu überwachendeCode # wird bei Exception ausgeführt # wird ausgeführt, wenn keine Ex # wird immer ausgeführt Tritt eine Ausnahme auf, hört der Interpreter auf, weitere Anweisungen im try-Block auszuführen und sucht nach einer except-Klausel, die zu der Ausnahme passt. Wenn eine solche Klausel gefunden wird, wird die Kontrolle an die erste Anweisung dieser except-Klausel abgegeben. Sonst wird die Ausnahme an den übergeordneten Block weitergegeben, der die try-Anweisung enthält, in der die Ausnahme aufgetreten ist. Wenn eine Ausnahme bis auf die höchste Programmebene weitergereicht wird, ohne abgefangen zu werden, terminiert der Interpreter mit einer Fehlermeldung. 22 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Weitere Operationen – hier einmal mit einer Exception programmiert >>> for key in Adjazenzliste: value = Adjazenzliste.get (key) try: value.remove ("C") Adjazenzliste.update ({key:value}) except ValueError: continue A B E D >>> Adjazenzliste {'A': ['A', 'B'], 'B': [], 'E': ['A'], 'D': ['A']} >>> A B E D 23 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Ein Tipp Sie sollten jetzt einmal versuchen, eine Klasse Graph in Python zu implementieren: Fangen Sie insbesondere alle Fehlersituationen ab: Knoten der eingefügt werden soll, ist schon vorhanden Kante, die gelöscht werden soll, ist nicht vorhanden usw., usw. Sorry, aber Übung muss sein, und Programmieren erfordert Disziplin, Ausdauer, abstraktes Denkvermögen, Kreativität und hohe Lernbereitschaft! 24 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 8 Noch eine Variante zur Implementierung von Graphen: Inzidenzmatrix (selten genutzt) ‣ Ein Graph mit n Knoten und m Kanten kann auch durch eine n×m-Matrix repräsentiert werden. Dazu nummeriert man die 2 Knoten von 1 bis n und die Kanten von 1 bis m durch und 3 trägt in die Matrix die Beziehungen der Knoten zu den Kanten ein. ‣ Jede Spalte der Inzidenzmatrix enthält bei Schleifenfreiheit genau zwei von Null verschiedene Einträge. 4 In ungerichteten Graphen zweimal die 1 und in gerichteten Graphen einmal die 1 (Endknoten) und einmal die -1 (Startknoten). 25 1 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker 1 2 3 1 -1 -1 1 2 1 3 4 5 -1 1 1 -1 4 -1 1 Hier wird Wissen Wirklichkeit Baum Als Wald bezeichnet man in der Graphentheorie einen ungerichteten Graphen ohne Kreis (Zyklus). Achtung: Zyklus ≠ Schleife Ist dieser zusammenhängend, so spricht man von einem (ungerichteten) Baum. Ein Wald besteht aus einem oder mehreren Bäumen. Jeder ungerichtete Baum ist also auch ein Wald. 26 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Gewurzelte Bäume Neben ungerichteten Bäumen betrachtetet man auch gerichtete Bäume, die häufig auch als gewurzelte Bäume bezeichnet werden und sich weiter in In-Trees und Out-Trees unterscheiden lassen. Es gibt einen ausgezeichneten Knoten, den man Wurzel nennt und für den die Eigenschaft gilt, ‣ dass alle Kanten von diesem wegzeigen (Out-Tree) oder ‣ zu diesem hinzeigen (In-Tree). 27 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 9 Eigenschaften die lineare Struktur der Liste wird aufgebrochen. Der maximale Ausgangsgrad wird als Ordnung eines Out-Trees bezeichnet (im Beispiel =3) Alle Knoten mit Ausgangsgrad = 0 bezeichnet man als Blätter. Alle Knoten, die kein Blatt sind, als innere Knoten. (Manchmal schließt man die Wurzel dabei aber aus.) Als Tiefe einen Knotens bezeichnet man die Länge des Pfades von der Wurzel zu ihm und als Höhe des Baums die Länge eines längsten Pfades. 28 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Eigenschaften Für einen von der Wurzel verschiedenen Knoten v bezeichnet man den Knoten, durch den er mit einer eingehenden Kante verbunden ist als Vater, Vaterknoten, Elternknoten oder Vorgänger von v. Als Vorfahren von v bezeichnet man alle Knoten, die entweder Vater von v oder Vorgänger des Vaters sind. Umgekehrt bezeichnet man alle Knoten, die von einem beliebigen Knoten v aus durch eine ausgehende Kante verbunden sind als Kinder, Kinderknoten, Sohn oder Nachfolger von v. Als Nachfahren von v bezeichnet man Kinder von v oder deren Nachfahren. Als Geschwister oder Geschwisterknoten werden in einem Out-Tree Knoten bezeichnet, die den gleichen Vater besitzen. 29 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Spezielle Bäume ‣ Bei Binärbäumen ist die Anzahl der Kinder höchstens zwei. ‣ In balancierten Bäumen gilt, dass sich die Höhen des linken und rechten Teilbaums an jedem Knoten höchstens um eins unterscheiden. ‣ Bei Suchbäumen sind die Elemente in der Baumstruktur geordnet abgelegt, so dass man schnell Elemente im Baum finden kann. 30 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 10 Partiell geordneter Baum Ein partiell geordneter Baum T ist ein Baum, ‣ dessen Knoten markiert sind ‣ dessen Markierungen aus einem geordneten Wertebereich stammen ‣ in dem für jeden Teilbaum T' mit der Wurzel x gilt: Alle Knoten aus T' sind größer markiert als x oder gleich x. Intuitiv bedeutet dies: Die Wurzel jedes Teilbaumes stellt ein Minimum für diesen Teilbaum dar. Die Werte des Teilbaumes nehmen in Richtung der Blätter zu oder bleiben gleich. 31 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Geordnete, strikte und vollständige Binärbäume ‣ Ein Binärbaum heißt geordnet, wenn jeder innere Knoten ein linkes und eventuell zusätzlich ein rechtes Kind besitzt (und nicht etwa nur ein rechtes Kind). ‣ Man bezeichnet ihn als voll oder strikt, wenn jeder Knoten entweder Blatt ist (also kein Kind besitzt), oder aber zwei (also sowohl ein linkes wie ein rechtes) Kinder besitzt. ‣ Man bezeichnet ihn als vollständig, wenn alle Blätter die gleiche Tiefe besitzen. Ein vollständiger Binärbaum der Höhe n, n man häufig auch als Bn bezeichnet, hat genau 2i Knoten in Tiefe i, insbesondere also ‣ 2n+1-1 Knoten, 2n Blätter ‣ 2n-1 innere Knoten, mit Höhe n die Länge des Pfades zu einem tiefsten Knoten bezeichnet wird. 32 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Eine wichtige Operation auf Bäumen: Linearisierung oder Traversierung Es gibt verschiedene Möglichkeiten, die Knoten von Binärbäumen zu durchlaufen. Diesen Prozess bezeichnet man auch als Linearisierung oder Traversierung. Man unterscheidet hier in: ‣ ‣ 33 pre-order (W–L–R): wobei zuerst die Wurzel (W) betrachtet wird und anschließend zuerst der linke (L), dann der rechte (R) Teilbaum durchlaufen wird, in-order (L–W–R): wobei zuerst der linke (L) Teilbaum durchlaufen wird, dann die Wurzel (W) betrachtet wird und anschließend der rechte (R) Teilbaum durchlaufen wird und Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 11 ‣ post-order (L–R–W): wobei zuerst der linke (L), dann der rechte (R) Teilbaum durchlaufen wird und anschließend die Wurzel (W) betrachtet wird. ‣ level-order Beginnend bei der Wurzel, werden die Ebenen von links nach rechts durchlaufen. 34 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Rekursive Implementierungen Funktion Preorder (Baum) W <- Baum.Wurzel If Baum.Links <> NULL L <- Preorder(Baum.Links) If Baum.Rechts <> NULL R <- Preorder(Baum.Rechts) Return W°L°R Funktion Inorder (Baum) W <- Baum.Wurzel If Baum.Links <> NULL L <- Inorder(Baum.Links) If Baum.Rechts <> NULL R <- Inorder(Baum.Rechts) Return L°W°R //W:= Wurzel des übergebenen Baumes //Existiert ein linker Unterbaum? // dann: L:= Preorder von linkem Unterbaum //Existiert ein rechter Unterbaum? // dann: R:= Preorder von rechtem Unterbaum //Rückgabe: Verkettung aus W, L und R /W:= Wurzel des übergebenen Baumes //Existiert ein linker Unterbaum? // dann: L:= Inorder von linkem Unterbaum //Existiert ein rechter Unterbaum? // dann: R:= Inorder von rechtem Unterbaum //Rückgabe: Verkettung aus L, W und R Funktion Postorder (Baum) W <- Baum.Wurzel //W:= Wurzel des übergebenen Baumes If Baum.Links <> NULL //Existiert ein linker Unterbaum? L <- Postorder(Baum.Links) // dann: L:= Postorder von linkem Unterbaum If Baum.Rechts <> NULL //Existiert ein rechter Unterbaum? R <- Postorder(Baum.Rechts) // dann: R:= Postorder von rechtem Unterbaum Return L°R°W //Rückgabe: Verkettung aus L, R und W 35 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Man unterscheidet hier weiter ‣ in binäre Suchbäume mit AVL-Bäumen als balancierte Version und ‣ B-Bäumen sowie diversen Varianten, den B*-Bäumen (die Blattknoten in einer Liste miteinander verkettet). (Spezielle Suchbäume häufig in Datenbanksystemen Achtung: B steht nicht für binär!) ‣ In B*-Bäumen wird neben der effizienten Suche einzelner Datenelemente auch das schnelle sequenzielle Durchlaufen aller Datenelemente unterstützt). Eine detaillierte Diskussion würde hier zu weit führen, aber Sie werden in Ihrem Studium noch viel davon hören, versprochen ;-) 36 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 12 Bäume als Datenstruktur Gewurzelte Bäume, insbesondere Out-Trees, Bei beschränkter Ordnung können diese so implementiert werden, dass jeder Knoten einen festen Satz an Variablen oder ein Array für die Referenzen auf seine Kinder enthält. Ein Baum unbeschränkter Ordnung kann implementiert werden, indem man statt Arrays dynamische Listen verwendet (z. B. in Python). Häufig besitzen die Knoten auch eine Referenz auf ihren Elternknoten (back pointer). 37 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Bäume als Datenstruktur (2) In Programmiersprachen ohne dynamische Listen hat sich auch ein Verfahren bewährt, bei dem ein allgemeiner Baum durch einen Binärbaum implementiert wird rote Linie zeigt dabei den realisierten allgemeinen Baum Pfeile zeigen die tatsächlich implementierte Zeigerstrukturen repräsentieren. Prinzip: linke Zeiger zeigt auf den am weitesten links stehenden Sohn rechte Zeiger auf den rechten Bruder verweist. 38 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Heap ‣ ‣ Der Heap (Haufen, Halde) vereint die Datenstruktur eines Baums mit den Operationen einer Vorrangwarteschlange. Je nach Reihenfolge in der Vorrangwarteschlange spricht man von Min-Heap oder einem Max-Heap. ‣ Häufig hat der Heap neben den minimal nötigen Operationen wie insert, remove und extractMin (-Max)auch noch weitere Operationen wie merge oder changeKey. ‣ In einem Heap können Objekte oder Elemente abgelegt und aus diesem wieder entnommen werden. Sie dienen damit der Speicherung von Mengen. Den Elementen ist dabei ein Schlüssel zugeordnet, der die Priorität der Elemente festlegt. Häufig werden auch die Elemente selbst als Schlüssel verwendet. 39 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 13 Übersicht ... zur Implementierung Implementierung mit einer dynamischen Liste in Python „einfach“ und effizient möglich Î Übung Graph gerichtet azyklisch ··· Baum tree M-Way binary tree 40 quadtree Suchbaum Halde search tree heap ··· octtree Programmieren 1 – Teil 1 – V10 WS 2007/2008 ·· B-Tree Wir betrachten eine Variante zur Übung ... Programmierung einer Klasse! · Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Ein Beispiel für die (unvollständige) Implementierung eines binären Suchbaums class Node: def __init__(self, data=None): self.data = data self.left = None self.right = None def __str__(self): return "[%s, %i, %i]" % (str(self.data), id(self.left), id(self.right)) 41 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Implementierung eines binären Suchbaums (2) class BTree: def __init__(self): self.root = None def _prchilds(self, node): if node != None: return "(%s; %s; %s)" (self._prchilds(node.left), node, self._prchilds(node.right)) else: return "nil" 42 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 14 Implementierung eines binären Suchbaums (3) def add(self, data): if self.root == None: self.root = Node(data) else: curnode = self.root lastnode = self.root while curnode != None: lastnode = curnode if data < curnode.data: curnode = curnode.left direction = -1 # links einfügen else: curnode = curnode.right direction = +1 # rechts einfügen if direction == -1: lastnode.left = Node(data) else: lastnode.right = Node(data) 43 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Testen unserer Implementierung in der Python Shell >>> a=BTree() >>> a.add(4) >>> a.add(2) >>> a.add(7) >>> a <__main__.BTree instance at 0x00C26828> >>> a.__str__() '((nil; [2, 505028048, 505028048]; nil); [4, 13095440, 13095880]; (nil; [7, 505028048, 505028048]; nil))' 44 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Zusammenfassung ‣ Graphen, Bäume, Heaps ‣ ganz wichtige Datenstrukturen ‣ Sie wissen, was das ist und wissen, wie es zu implementieren ist ‣ es fehlen aber noch viele weitergehende Aspekte, ... Datenstrukturen im 2. Semester, ... Programmieren erfordert Disziplin, Ausdauer, abstraktes Denkvermögen, Kreativität und hohe Lernbereitschaft! 45 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 15 Fragen und (hoffentlich) Antworten 46 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit Ausblick Der Abschluss des Teils 1 am Freitag (für die Klausur immerhin schon 45%): jeweils nur ausgewählte Elemente: ‣ Module, Pakete ‣ Ein- / Ausgabe ‣ Exceptions und event-based programming ‣ und eine 1. Evaluierung Danke für Ihre Aufmerksamkeit! 47 Programmieren 1 – Teil 1 – V10 WS 2007/2008 Prof. Dr. Detlef Krömker Hier wird Wissen Wirklichkeit 16