Kapitel 5: Von Datenstrukturen zu Abstrakten Datentypen

Slides:



Advertisements
Ähnliche Präsentationen
8. Termin Teil B: Wiederholung Begriffe Baum
Advertisements

Randomisierte Algorithmen Präfix Suche und Konsistentes Hashing
Punkt-in-Polygon-Verfahren III (R/R+-Baum)
Man bestimme den „minimalen aufspannenden Baum“ des Graphen.
Eine dynamische Menge, die diese Operationen unterstützt,
Minimum Spanning Tree: MST
Prof. Dr. S. Albers Prof.Dr.Th Ottmann
Algebraische Zahlen: Exaktes Rechnen mit Wurzeln
7.2 B-Bäume / B*-Bäume als Hilfsmittel zur Indexorganisation
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Claudio Moraga; Gisbert Dittrich
Graphen Ein Graph ist eine Kollektion von Knoten und Kanten. Knoten sind einfache Objekte. Sie haben Namen und können Träger von Werten, Eigenschaften.
Das LCA – Problem in Suffixbäumen
GIN2 – 2. Vorlesung, SS04 Prof. Dr. Wolfram Conen
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (22 – B-Bäume)
Kapitel 6: Klassifizierung von Sortiertechniken
7. Natürliche Binärbäume
R. Der - Vorlesung Algorithmen und Datenstrukturen (Magister)
Bäume • Kernidee: Speicherung von Daten in einer Baumstruktur
Sortierverfahren Richard Göbel.
Sortierverfahren Richard Göbel.
Algorithmentheorie 04 –Hashing
WS Algorithmentheorie 05 - Treaps Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (23 – Sortieren vorsortierter Daten) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (19 - Analyse natürlicher Bäume) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (27 – Kürzeste Wege) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (17 – Bäume: Grundlagen und natürliche Suchbäume) Prof. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen 09 - Weitere Sortierverfahren Heapsort-Nachtrag Prof. Th. Ottmann.
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (21 – Kürzeste Wege) T. Lauer.
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (17 – Fibonacci-Heaps – Analyse) Tobias Lauer.
WS Algorithmentheorie 15 – Fibonacci-Heaps Tobias Lauer.
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (17 – Fibonacci-Heaps) Tobias Lauer.
Algorithmentheorie 12 – Spannende Bäume minimalen Gewichts
Union-Find-Strukturen
WS Algorithmentheorie 15 – Fibonacci-Heaps Tobias Lauer.
Algorithmen und Datenstrukturen
WS03/041 Binomial Queues Prof. Dr. S. Albers Prof.Dr.Th Ottmann.
Kapitel 6 Differenzierbarkeit. Kapitel 6: Differenzierbarkeit © Beutelspacher Juni 2005 Seite 2 Inhalt 6.1 Die Definition 6.2 Die Eigenschaften 6.3 Extremwerte.
Seminar parallele Programmierung SS 2003
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 12 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Heaps und Priority Queues
Minimum Spanning Tree: MST
Kapitel 2: Datenstrukturen
Punktbeschriftung mit vier Rechtecken gleicher Höhe (Anzahlmaximierung) Julia Löcherbach.
7.1 Externes Suchen Bisherige Algorithmen: geeignet, wenn alle Daten im Hauptspeicher. Große Datenmengen: oft auf externen Speichermedien, z.B. Festplatte.
Splay Trees Von Projdakov Benjamin.
2. Die rekursive Datenstruktur Baum 2
Effiziente Algorithmen
Diskrete Mathematik II
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen
Effiziente Algorithmen
Black Box Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Effiziente Algorithmen
Effiziente Algorithmen Hartmut Klauck Universität Frankfurt SS
Information und Kommunikation Hartmut Klauck Universität Frankfurt SS
Information und Kommunikation
Information und Kommunikation Hartmut Klauck Universität Frankfurt SS
Graphen und Bäume.
Kapitel 8: Graphalgorithmen 8. 1 Grundlagen 8
Kapitel 6: Suchbäume und weitere Sortierverfahren
Kapitel 8: Graphalgorithmen 8. 1 Grundlagen 8
Analyse der Laufzeit von Algorithmen
Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik II Vorlesung Datenstrukturen für den Algorithmus von.
Binärbäume.
Programmiersprachen II Vorbesprechung Klausur Prof. Dr. Reiner Güttler Fachbereich GIS HTW.
2. Die rekursive Datenstruktur Baum 2.1 Von der Liste zum Baum
 Präsentation transkript:

Kapitel 5: Von Datenstrukturen zu Abstrakten Datentypen 5.1   Zur Erinnerung: Datenstrukturen in Pascal Listenverarbeitung in Pascal 5.2   Abstrakte Datentypen und Objektorientierung Brüche als ADT Implementierung - objektorientiert Brüche als ADT Implementierung - funktional 5.3   Geordnete lineare Zusammenfassungen: Listen bzw. Folgen Cons-Zelle als Basisklasse Statisch-funktionale Listenimplementierung Listenimplementierung mit Objektmethoden 5.4   Stacks und Queues Zustandsorientierte Stack-Implementierung 5.5   Priority Queues 5.6   Find and Merge 5.6.1   Implementierung mit Arrays 5.6.2   Implementierung mit Bäumen

Implementierung von Queues: Mit doppelt verketteter Liste als Zeigerstruktur Doppelt verkettet, da man auf beide Enden der Liste zugreifen muss. In einem Array Problem: Einfügen am Ende und Entfernen am Anfang führt dazu, dass die Queue „durch den Array wandert“. Lösung: Zyklisch in einem Array

Anwendungen von Queues Realisierung von Warteschlangen, besonders in Betriebssystemen, z.B. Prozesse, Nachrichten, Druckaufträge.

5.5 Priority Queues: Mengen mit Insert und Deletemin Priority Queues: Warteschlangen, in denen die Elemente Prioritäten haben. Es können Elemente mit beliebiger Priorität eingefügt werden und es wird immer das (ein) Element mit der höchsten Priorität entnommen. Anwendungen/Beispiele: Patienten im Warteraum einer Krankenhausambulanz Betriebssysteme, bes. Multiuser-Betriebssysteme

Oft können verschiedene Elemente gleiche Priorität haben: führt zu Multisets (Multimengen) Multisets: Mengen mit Duplikaten (aber ohne Ordnung der Elemente, also keine Listen/Folgen). Beispiel: {|1,3,3,7,7,7,10|} auch notiert als: {(1,1),(3,2),(7,3),(10,1)} Zu einer Menge S sei M(S) die Menge aller Multimengen mit Elementen aus S. In Priority Queues: Prioritäten = natürliche Zahlen Höhere Priorität = kleinere Zahl (dann gibt es automatisch eine höchste Priorität).

Datentyp für die Priority Queue, algebraische Spezifikation: algebra pqueue sorts   pqueue, elem ops     empty:                  pqueue       isempty: pqueue         boolean       insert: pqueue  elem  pqueue       deletemin: pqueue       pqueue  elem sets    pqueue = M(elem) functions       empty = {}       isempty (p)  = (p={})       insert (p,e) = p  {|e|}       deletemin (p) = (p',e)         mit e = min(p) und p'=p\{|e|} falls p{},          undefiniert sonst end pqueue.

Implementierung von Priority Queues Z.B. mit partiell geordneten Bäumen. Ein partiell geordneter Baum (Heap) ist ein knotenmarkierter binärer Baum (T, m) (hier ist T der Baumgraph und m die Markierungsfunktion der Knoten), in dem für jeden Teilbaum (T ',m) mit der Wurzel x gilt:             für alle y aus T ' ist m(x)  m(y) In der Wurzel steht also jeweils das Minimum eines Teilbaumes. Analog möglich: Ordnung umgekehrt, also in jeder Wurzel eines Teilbaums das Maximum.

Definition Heap Speziellere Definition eines Heap: partiell geordneter Binärbaum, der links-vollständig ist, d.h. die Ebenen werden von der Wurzel her gefüllt, und jede Ebene von links nach rechts. Außerdem: Implementierung in einem Array, in dem die Knoten in dieser Reihenfolge abgelegt werden.

Teilheap Ein Teil T [ i..k ] ( 0  i  k  n ) heißt Teilheap, wenn gilt:         für alle j aus {i,...,k} ist     m(T [ j ])  m(T [ 2j ])     falls 2j  k                                       und   m(T [ j ])  m(T [ 2j+1])  falls 2j+1  k Ist T [i+1..n] bereits ein Teilheap, so kann man durch Einsinkenlassen des Elements T [ i ] die Heapeigenschaft erweitern.

Aufbau des Heaps Zum Aufbau des Heaps werden die Elemente zunächst in die Ebenen unterhalb der Wurzel eingebracht und zwar maximal 2 j  Elemente in die Ebene j (j = 0,..., k-1). Jedes Einsinkenlassen eines Elementes kostet den Aufwand O(k-1) = O(ld n), also bei n Elementen O(n ld n). Eine genauere Betrachtung zeigt, dass der Aufwand pro Element in jeder j-Ebene nur O(k-j-1) ist. Also erhält man allgemein         1 •2 k-2 + 2 • 2 k-3 + ... + (k-1) • 2 0  2 k-1 i > 0  i / 2i = 2 k = O(n) Hat man nun das oberste Element entfernt, so wird das letzte Element an seine Stelle gebracht und durch Einsinken- lassen (pro Ebene zwei Vergleiche und eine Vertauschung) die Heapeigenschaft wiederhergestellt. Dies kostet einen Aufwand von O(ld n).

Entfernen des minimalen Elementes aus einem Heap und Wiederherstellung der Heapeigenschaft Algorithmus deletemin (h) {lösche das minimale Element aus dem Heap h und gib es aus} Entnimm der Wurzel ihren Eintrag und gib ihn als Minimum aus. Nimm den Eintrag der letzten besetzten Position im Baum, lösche diese Position und setze ihren Eintrag in die Wurzel ein. Sei p die Wurzel, und seien q und r die Söhne der Wurzel Solange Söhne q oder r existieren und (m(p) > m(q) oder m(p) > m(r) ) gilt: {vertausche p mit dem Sohn mit dem kleineren Eintrag. Setze q und r auf die neuen Söhne dieses Knotens.}

Einfügen in einen Heap: Algorithmus insert (h, e) {füge einen neuen Knoten q mit Eintrag e in den Heap h ein} erzeuge einen neuen Knoten q mit Eintrag e; füge q auf der ersten freien Position in der untersten Ebene ein; falls die unterste Ebene voll besetzt ist, beginne eine neue Ebene. Sei p der Vater von e; Solange p existiert und m(p) > e gilt: {Vertausche die Einträge in p und q, setze q auf p und p auf den Vater von p.}

Sei n die Zahl der Knoten des Heap. Aufwand für das Entfernen des minimalen Elementes: O(log n). für das Einfügen eines neuen Knotens: O(log n). Denn ein Heap hat Höhe [log2 (n+1)]+ -1 für das Aufbauen des Heap durch wiederholtes Einfügen von Knoten: O(n log n). Wir haben gesehen, dass man einen Heap in O(n) Schritten aufbauen kann, wenn diese Elemente von Anfang an alle bekannt sind.

5.6 Partitionen von Mengen mit Find und Merge Sei S eine Menge, P eine Partition von S, also eine Menge von Teilmengen von S, die paarweise disjunkt sind und zusammen die Menge S ergeben. (Zwei Elemente von S heißen äquivalent, wenn sie zur gleichen Komponente gehören.) Wir wollen: find: bei Eingabe eines Elementes die Komponente finden, zu der es gehört, merge: bei Eingabe (der Namen oder von Elementen) zweier Komponenten diese verschmelzen.

Datentyp, algebraisch spezifiziert: algebra partition sorts   partition, compname, elem ops     empty :   partition   addcomp: partition  compname  elem  partition   merge : partition  compname  compname  partition   find : partition  elem  compname sets    compname=Menge von Komponentennamen (aus einer Menge CN) partition={(ci ,Si) | 1  i  n, ci Komponentenname, Si Teilmenge von elem,                   ij  ci  cj und Si, Sj elementfremd.}

functions empty bildet auf die leere Partition ab (dann ist auch die partitionierte Menge S die leere Menge!) Sei p:={(c1,S1), ..., (cn,Sn)} eine Partition, S = Vereinigung der Si, und C= {c1, ..., cn}, C Komp. N. Sei a aus CN\C, x nicht in S enthalten.      addcomp(p,a,x) =p U {(a,{x})}         Seien a und b Elemente aus C mit den zugehörigen      Komponenten A und B, d ein Name aus CN\C oder d=a bzw. d=b. merge (p,a,b) = (p \ {(a,A), (b,B)}) U {(d,A U B)}     Sei x ein Element aus S.  find (p,x) = a mit (a,A) aus p und x aus A. end partition.

5.6.1 Implementierung mit Arrays Fall elem := {1,..., n} und compname = {1,..., n}. Wir benutzen zwei Arrays der Größe n. Adjazenzmatrix (components): enthält die Komponentennamen und zu jedem ein Element der Komponente (wenn dies 0, dann Komponente leer). Inzidenzmatrix (elems): enthält die Elementnamen, zu jedem den Namen der zugehörigen Komponente und ein weiteres Element der Komponente (wenn dies 0, dann kein noch nicht erfasstes Element der Komponente). Man erhält für jede Komponente eine verkettete Liste!

Vertreter (0 unbenutzt) Beispiel p = {(2,{1,2,4,5}), (3,{3}), (6,{6})}. S = {1,2,3,4,5,6}. components  compname Vertreter (0 unbenutzt) verlinkt mit 1   2 mit 1 3 mit 3 4 5 6 mit 6 elems compname nextelem 1 2 4 3 0 (entspricht NIL) 5 6

Algorithmus find: Zeit O(1). Algorithmus merge (p, a, b); {verschmelze die Komponenten von a und b in der Partition p} Durchlaufe für a die zugehörige Liste in der Inzidenzmatrix elems und setze für jedes Element der Liste den zugehörigen Komponentennamen compname auf b; Sei j der Name des letzten Elements dieser Liste; Führe dann die folgenden Umbenennungen durch. elems[j].nextelem:= components[b].firstelem; components[b].firstelem:=components[a].firstelem; components[a].firstelem:=0; end merge.

Aufwand für merge: O(n). Aufwand für n-1 merge-Anweisungen: Klar: O( Σi=1…n i) = O(n²). Kann verbessert werden zu: O(n log n): Schlage immer die kleinere Komponente zur größeren! Dann immer eine (mindestens) Verdoppelung der Größe der Komponente eines Elements. Amortisierte worst-case Laufzeit von merge: O(log n).

5.6.2 Implementierung mit Bäumen Wir benutzen: ein Array mit den Elementen und für jedes Element einen Knoten in einem Baum, sowie zu jeder Komponente eine Baumstruktur. Name einer Komponente: das Element in der Wurzel des Baums.

Implementation mit Bäumen elems 1 -> 1 2 -> 2 3 -> 3 -> K3 -> 3 4 -> 4 -> 1 -> K2 -> 1 5 -> 5 6 -> 6 -> K6 -> 6 Hier wird jede Komponente durch einen Baum dargestellt, dessen Knoten die Elemente der Komponente sind. Dann ist elems ein array[1..n]  von diesen Bäumen. Die Verweise führen von den Söhnen zum Vater, die Namen der Komponenten sind Zeiger auf die Wurzeln der zugehörigen Bäume: Der Wurzelknoten enthält neben dem Namen der Komponente noch deren Größe.

Algorithmen find(p,x): starte im Array bei x und laufe zur Wurzel des Baums der Komponente. Aufwand: O( Höhe des Baums). merge(p,a,b): Mache a zum Sohn von b oder umgekehrt. Aufwand: O(1). Höhenbeschränkung zu erreichen durch: Wurzel der kleineren Komponente wird Sohn der Wurzel der größeren Komponente. Dann: Höhe  log n.

Pfadkompression Noch eine Verbesserung: Pfadkompression: bei find(p,x) mache alle Knoten auf dem Pfad von x zur Wurzel zu Söhnen der Wurzel. Dann n find-Operationen beinahe in linearer Zeit: O(n • G(n)) Dabei wächst G sehr langsam: G(n)  5 für n  265536.

Kapitel 6: Suchbäume und weitere Sortierverfahren 6.1   Binäre Bäume Die Klasse BinTree mit Traversierungsmethoden 6.2   Suchbäume 6.2.1   AVL Bäume 6.3   HeapSort und BucketSort 6.3.1   HeapSort 6.3.2   BucketSort

6.1 Binäre Bäume Bäume als Graphen: Gerichtete Graphen: bestehen aus Knoten (Knotenmenge V) und Kanten (Kantenmenge E:Teilmenge von V V). Bäume: spezielle gerichtete Graphen: (1) haben einen ausgezeichneten Knoten, die Wurzel w, (2) haben die Eigenschaft, dass zu jedem Knoten k des Baumes genau eine Kantenfolge (ein Pfad) existiert, die w mit k verbindet. (3) haben keine Zykeln, d.h. es gibt keine Kantenfolge, die den gleichen Knoten mit sich verbindet. Bäume: andere Charakterisierung: zusammenhängende gerichtete Graphen mit #(V) = #(E) + 1.

Graphische Darstellung Bäume werden graphisch i.d.R. so dargestellt, dass die Wurzel die oberste Position einnimmt und Kanten von oben nach unten gerichtet sind (Hierarchie). Knoten, von denen keine weiteren Kanten ausgehen, heißen äußere Knoten oder Blätter. Die anderen Knoten heißen innere Knoten.

Beispiel: Binärbaum zum Ausdruck ((12/4)•2) Hier: innere Knoten: Kreise Blätter: Rechtecke

Bezeichnungen Ist (k,k´) eine Kante in einem Baum, so heißt k´ Kind (Sohn, Nachfolger) von k und k Vorgänger von k´. Nachfolgerrelation eines Baumes: { (k, k´) | k innerer Knoten, k´ Nachfolger von k´} Vorgängerfunktion eines Baumes: partielle Funktion, die jedem Knoten außer der Wurzel den Vorgänger zuordnet.

Binärbäume: Bäume, in denen jeder Knoten maximal zwei Nachfolger hat. Direkte Definition von Binärbäumen: T ist genau dann ein Binärbaum (mit Knotenelementen aus M), wenn (i) T = < T1, x, T2 >  wobei T1, T2 Binärbäume und x aus M oder (ii) T = < > (leere Struktur, null)

Hier: Bei einem Binärbaum T = < T1, x, T2 > ist x die Wurzel des Baums. Knoten: die Wurzeln von Teilbäumen. Kanten: von der Wurzel x eines Teilbaumes T = < T1, x, T2 > zu den Wurzeln von T1 und T2. Wir identifizieren im Folgenden häufig einen Knoten mit dem entsprechenden Wert (Inhalt) x. Ein Knoteninhalt kann in einem Binärbaum mehrfach vorkommen. Eindeutige Identifizierung eines Knoten: durch Links-/Rechts-Entscheidungen von der Wurzel zu dem Knoten: Bitfolge. Diese Definition kann auf k-näre Bäume erweitert werden.

Pfade Pfad: Knotenfolge x0 , x1 , ... , xn , wobei jeweils xi+1 Nachfolger (Kind) von xi ist, d.h. (xi,xi+1) Kante. Länge eines Pfades = Zahl der Kanten, hier also n. Ein nur aus einem Knoten bestehender Pfad hat die Länge 0.

Die Höhe eines Baumes T ist die maximale Länge eines Pfades in T. (Die Anzahl der Ebenen im Baum ist um eins größer als die Höhe des Baumes.) Ein Binärbaum heißt vollständig, wenn alle Ebenen bis auf die letzte vollständig besetzt sind. … links-vollständig, wenn er vollständig ist und die unterste Ebene von links nach rechts aufgefüllt ist. Auch diese Definitionen gelten für k-näre Bäume