Datenstrukturen und Algorithmen

Ähnliche Dokumente
Datenstrukturen & Algorithmen

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Technische Universität Wien Institut für Computergraphik und Algorithmen Arbeitsbereich für Algorithmen und Datenstrukturen

Was bisher geschah ADT Menge mit Operationen: Suche nach einem Element Einfügen eines Elementes Löschen eines Elementes Realisierung durch

12 (2-4)-Bäume Implementierbare Funktionen. (2-4)-Bäume sind durch folgende Eigenschaften deniert: 1. Alle Äste sind gleich lang

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2012/13. Prof. Dr. Sándor Fekete

Algorithmen und Datenstrukturen Balancierte Suchbäume

Klausur Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen Suchbaum

Alle bislang betrachteten Sortieralgorithmen hatten (worst-case) Laufzeit Ω(nlog(n)).

Abgabe: (vor der Vorlesung) Aufgabe 2.1 (P) O-Notation Beweisen Sie die folgenden Aussagen für positive Funktionen f und g:

14. Rot-Schwarz-Bäume

Algorithmen und Datenstrukturen

Datenstrukturen. Mariano Zelke. Sommersemester 2012

Datenstrukturen und Algorithmen

Definition Ein gerichteter Graph G = (V, E) ist ein Graph von geordneten Paaren (u, v) mit u V und v V.

3. Musterlösung. Problem 1: Boruvka MST

Datenstrukturen und Algorithmen

Übersicht. Datenstrukturen und Algorithmen Vorlesung 5: Rekursionsgleichungen (K4) Übersicht. Binäre Suche. Joost-Pieter Katoen. 20.

Wiederholung ADT Menge Ziel: Verwaltung (Finden, Einfügen, Entfernen) einer Menge von Elementen

Datenstrukturen & Algorithmen

Graphalgorithmen 2. Oleksiy Rybakov. 3. Juni Betreuer: Tobias Werth, Daniel Brinkers

Ein Graph ist ein Paar (V,E), wobei V eine Menge von Knoten und E eine Menge von Kanten (v,w) mit v,w in V ist.

Algorithmen - Eine Einführung

Datenstruktur, die viele Operationen dynamischer Mengen unterstützt

1. Einfach verkettete Liste unsortiert 2. Einfach verkettete Liste sortiert 3. Doppelt verkettete Liste sortiert

Programmiertechnik II

Abschnitt 18: Effizientes Suchen in Mengen

Kapitel 9 Suchalgorithmen

2. Übungsblatt zu Algorithmen II im WS 2016/2017

Technische Universität Wien Institut für Computergraphik und Algorithmen Arbeitsbereich für Algorithmen und Datenstrukturen

16. All Pairs Shortest Path (ASPS)

Rekurrenzen T(n) = T(n 1) + N beschreibt Laufzeitverhalten eines rekursiven Algorithmus

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Effiziente Algorithmen und Datenstrukturen I. Kapitel 9: Minimale Spannbäume

Grundlagen der Programmierung 2. Bäume

INSTITUT FÜR THEORETISCHE INFORMATIK, PROF. SANDERS

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / 2015 Vorlesung 3, Donnerstag 6.

Graphen: Datenstrukturen und Algorithmen

13. Binäre Suchbäume

Übersicht Datenstrukturen und Algorithmen. Literatur. Algorithmus: Wikipedia Definition. Vorlesung 1: Einführung. Prof. Dr.

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

3.1 Konstruktion von minimalen Spannbäumen Es gibt zwei Prinzipien für die Konstruktion von minimalen Spannbäumen (Tarjan): blaue Regel rote Regel

Aufgabe 4.2 Sei G = (V, E, l) ein ungerichteter, gewichteter und zusammenhängender Graph.

Algorithmen & Datenstrukturen 1. Klausur

Algorithmen und Datenstrukturen 1-1. Seminar -

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

WS 2009/10. Diskrete Strukturen

Algorithmen und Datenstrukturen in der Bioinformatik Viertes Übungsblatt WS 05/06 Musterlösung

Sortierverfahren für Felder (Listen)

Minimal spannende Bäume

κ(k) k K S Algorithmus zur Bestimmung eines spannenden Baumes mit minimalen Kosten (Kruskal, 1965).

Suchen und Sortieren Sortieren. Heaps

Datenstrukturen und SS Robert Elsässer

MafI I: Logik & Diskrete Mathematik (F. Hoffmann)

2 i. i=0. und beweisen Sie mittels eines geeigneten Verfahrens die Korrektheit der geschlossenen Form.

1. Motivation / Grundlagen 2. Sortierverfahren 3. Elementare Datenstrukturen / Anwendungen 4. Bäume / Graphen 5. Hashing 6. Algorithmische Geometrie

Proseminar Online Algorithmen, Prof. Dr. Rolf Klein

Einführung in Heuristische Suche

Babeș-Bolyai Universität Cluj Napoca Fakultät für Mathematik und Informatik Grundlagen der Programmierung MLG5005. Paradigmen im Algorithmenentwurf

Übung Algorithmen I

Vorlesung Datenstrukturen

Universität des Saarlandes

Informatik II, SS 2014

Algorithmen und Datenstrukturen

Kapitel 5: Dynamisches Programmieren Gliederung

Kap. 4.2: Binäre Suchbäume

Algorithmen und Datenstrukturen Kapitel 7 Dynamische Mengen, das Suchproblem &

Programmiertechnik II

4 Greedy-Algorithmen (gierige Algorithmen)

Bäume, Suchbäume und Hash-Tabellen

Suche in Spielbäumen Spielbäume Minimax Algorithmus Alpha-Beta Suche. Suche in Spielbäumen. KI SS2011: Suche in Spielbäumen 1/20

Referat zum Thema Huffman-Codes

Bäume. Text. Prof. Dr. Margarita Esponda SS 2012 O4 O5 O6 O ALP2-Vorlesung, M. Esponda

9. Übung Algorithmen I

WS 2009/10. Diskrete Strukturen

DATENSTRUKTUREN UND ALGORITHMEN

Übung zur Vorlesung Algorithmische Geometrie

S=[n] Menge von Veranstaltungen J S kompatibel mit maximaler Größe J

Algorithmen und Datenstrukturen Wintersemester 2004/ November T(n) = T(n a) + T(a) + n

Datenstrukturen & Algorithmen

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v)

23. November Betweenness Centrality Closeness Centrality. H. Meyerhenke: Algorithmische Methoden zur Netzwerkanalyse 108

Übersicht. Rot-schwarz Bäume. Rot-schwarz Bäume. Beispiel. Eigenschaften. Datenstrukturen & Algorithmen. Rot-schwarz Bäume Eigenschaften Einfügen

Kapitel 3: Untere Schranken für algorithmische Probleme Gliederung

Bäume und Wälder. Bäume und Wälder 1 / 37

Teil II: Prioritätslisten (Priority Queues)

Suchbäume mit inneren Knoten verschiedener Knotengrade.

Grundlagen der Programmierung

Vorlesung 4 BETWEENNESS CENTRALITY

Algorithmen und Datenstrukturen 2

Transkript:

Datenstrukturen und Algorithmen Jedes Programm verwendet Datenstrukturen und Algorithmen um seine Aufgabe zu erfüllen Diese müssen offenbar zunächst sorgfältig dem speziellen Problem entsprechend ausgewählt werden Hat man sich für solche D s und A s entschieden, müssen diese noch sorgfältig implementiert werden 2 Zur Beschreibung und Implementierung der Datenstrukturen und Algorithmen verwenden wir hier C++ Formulierung von Datenstrukturen als Objekte, Algorithmen als Funktionen Saubere Schnittstellenspezifikation und Klassendesign ist mindestens genauso wichtig wie die eigentliche Implementierung Der Berufsalltag der meisten Informatiker besteht weit häufiger aus dem Entwickeln solcher Spezifikationen als aus dem Schreiben von Programmcode 1

Nach welchen Kriterien wählt man Datenstrukturen und Algorithmen für ein spezielles Problem? Korrektheit (klar ) Laufzeit Speicherverbrauch Laufzeit und Speicherverbrauch kann man oft mit den selben Techniken analysieren. Daher sprechen wir im Folgenden nur von Laufzeiten. Wichtigste Werkzeuge: Asymptotische Notation Rekurrenzgleichungen Worst-Case und amortisierte Analyse 2

Asymptotische Notation Das Wachstum von Funktionen Für kleine Problemgrößen spielt die Laufzeit meist keine Rolle. Uns interessiert statt dessen die Laufzeit für große Probleminstanzen! Daher analysieren wir häufig das Laufzeitverhalten nur für genügend große Eingaben (Grenzwertprozess!) Dies motiviert die folgenden Wachstumsklassen: o(f(n)): alle Funktionen die langsamer wachsen als f (f(n)): alle Funktionen die nicht schneller wachsen als f Θ(f(n)): alle Funktionen die so schnell wachsen wie f Ω(f(n)): alle Funktionen die nicht langsamer wachsen als f ω(f(n)): alle Funktionen die schneller wachsen als f Genaue Definitionen: + Sei F = f : N R } die Menge aller Funktionen von N nach R 0+. { 0 Definition [1]: Für g F ist Θ( g) = { f F c1, c2 > 0 n0 N : n n0 : c1 g( n) f ( n) c2g( n)} O( g) = { f F c > 0 n0 N : n n0 : f ( n) cg( n)} Ω g) = { f F c > 0 n N : n n : f ( n) cg( )} ( 0 0 n o ( g) = { f F c > 0 n0 N : n n0 : f ( n) < cg( n)} ω( g ) = { f F c > 0 n0 N : n n0 : f ( n) > cg( n)} 3

Häufig lassen sich die folgenden Sätze einfacher anwenden als die Definitionen: Damit können wir jetzt Laufzeiten miteinander vergleichen. Aber woher kennen wir die Laufzeit eines Algorithmus? Bei iterativen Algorithmen ist es oft leicht, einfach die Anweisungen zu zählen (vgl. z.b. Musterlösung Blatt 4, Aufgabe 4) Die Analyse rekursiver Algorithmen führt hingegen meist auf eine sog. Rekurrenzgleichung 4

Beispiel: Mergesort(vector<int> A, int p, int r) { if (p<r) { int q = (p+r)/2; Mergesort(A,p,q); Mergesort(A,q+1,r); Merge(A,p,q,r); } } Θ(1) T(n/2) T(n/2) Θ(n) T(n) Dies ist eine Rekurrenzgleichung, denn T hängt vom Wert von T für kleinere Eingaben ab! Wie löst man Rekurrenzgleichungen? Wir haben zwei Verfahren dafür kennengelernt: Substitutionsmethode Mastertheorem 5

Lösung mit der Substitutionsmethode: - Rate eine Lösung (z.b. über den Rekursionsbaum) - Beweise die Korrektheit dieser Lösung per Induktion Lösung mit dem Mastertheorem: Mit dem Mastertheorem kann man sehr einfach Rekurrenzen der Form T(n) = at(n/b) + f(n) lösen Leider hat es aber zwei Definitionslücken, d.h. es gibt einige Rekurrenzen dieser Form, die nicht mit dem Mastertheorem lösbar sind Idee des Mastertheorems: vergleiche die Kosten für Aufspalten in Teilprobleme / Zusammensetzen zur Gesamtlösung (n log[b](a) ) Lösen der Teilprobleme (f(n)) 6

Der Vergleich der Kosten Aufspalten / Lösen kann offenbar drei verschiedene Ergebnisse haben: 1. Aufspalten/Zusammensetzen ist teurer Aufspalten/Zusammensetzen dominiert die Kosten (n log[b](a) ) 2. Kosten in etwa gleich Kosten dominiert durch Aufspalten/Zusammensetzen und Lösen (log(n) n log[b](a) ) 3. Lösen ist teurer Lösen dominiert die Kosten (f(n)) Kleiner Haken : teurer reicht leider nicht aus! Wir müssen bei 1. und 3. statt dessen wesentlich teurer verlangen! Unter wesentlich teurer verstehen wir, dass zwischen die beiden Funktionen noch mindestens ein Polynom passt, der Unterschied also mindestens polynomiell ist! Wir landen also bei den folgenden drei Fällen (a1, b>1, f(n)0): T ( n) = at( n / b) + f ( n) log ( a) ε log f n = O n für ein ε > 0, so gilt: b( a) T( n) = Θ( n ) b (1) Ist ( ) ( ) b (2) Ist ( ) ( ) f n log ( a) logb ( a) = Θ n dann ist: T( n) =Θ( n log( n) ) log ( a) + ε Erste Lücke Zweite Lücke b (3) Ist f ( n) =Ω( n ) für ein ε > 0, und ist a f(n/b) c f(n) für eine Konstante c < 1 und genügend großes n, so gilt: T( n) = Θ( f ( n)) 7

Je nach Anwendung verwendet man verschiedene Arten von Laufzeiten: Worst-Case Laufzeiten (schlimmer kann s nicht werden!) Erwartete Laufzeiten (Statistik über die möglichen Eingaben) Amortisierte Laufzeiten (in einer Sequenz von Operationen kann häufig nicht jedesmal der worst-case auftreten ) bessere Laufzeit der Gesamtsequenz. Beispiel: Sequenz von clear-operationen auf einem vector. Das erste clear läuft in O(n), die anderen in O(1), da ja nichts mehr zu tun ist.) Nachdem wir nun Laufzeiten bestimmen und interpretieren können, können wir einen Grundstock von allgemein verwendbaren Datenstrukturen und Algorithmen aufbauen Die am häufigsten benötigten Operationen einer Datenstruktur sind einfügen, löschen und suchen, daher sollte man von jeder Datenstruktur wissen, ob und wie effizient sie diese zur Verfügung stellt Aus diesen Datenstrukturen kann man dann die dem jeweiligen Problem am besten angepasste auswählen Meist ist die Wahl von Datenstrukturen und Algorithmen wesentlich wichtiger für die Laufzeit eines Programms als ein hoch optimierter Programmcode ein guter Informatiker sollte möglichst viele Datenstrukturen mit ihren Vor- und Nachteilen kennen 8

Datenstrukturen aus der Vorlesung: Unbounded arrays (vector in C++) Listen (einfach verkettet, doppelt verkettet, zyklisch, ) (Such-)Bäume und Wälder (binär, Rot-Schwarz, AVL, ) Heaps (Binär, d-när, Binomial, Fibonacci) Graphen (gerichtet, ungerichtet) Binäre Suchbäume 15 5 16 3 12 20 10 18 6 7 23 Daten im linken Teilbaum immer, im rechten Teilbaum immer den Daten in der Wurzel Einfügen/Löschen/Suchen: worst-case in (h) (Höhe des Baumes) Wir wollen möglichst geringe Höhe schon beim Aufbau des Baumes garantieren 9

Rot-Schwarz - Bäume 3 7 10 26 17 41 14 21 30 10 16 19 23 28 38 12 15 20 35 39 47 Die Bedingungen an die Farbe eines Knotens und damit an die Baumstruktur garantieren, dass kein Pfad von der Wurzel zu den Blättern mehr als doppelt so lang sein kann als ein anderer solcher Pfad der Baum ist beinahe balanciert Einfügen/Löschen/ Suchen in (log(n)) AVL-Bäume 14 Baum ist soweit wie möglich balanciert 5 16 3 12 15 20 (die Anzahl Knoten in jedem linken und jedem rechten Teilbaum unterscheidet sich um maximal 1) 2 Einfügen/Löschen/Suchen in (log(n)) 2-5 - Bäume 14 2 6 14 Balanciert und simpel, verschenken aber viel Speicher 1 2 4 5 6 11 14 10

Heaps Ein Heap ist ein Suchbaum, der die Heapeigenschaft erfüllt: Die Kinder sind immer extremer als die Eltern! Min-Heap: Wert der Eltern kleiner als der der Kinder Max-Heap: Wert der Eltern kleiner als der der Kinder 1 2 3 4 5 6 7 8 9 Heaps Einfügen geht bei Heaps effizient ((log(n)) Effizient Löschen können wir aber nur das maximale Element (max-heap) bzw. das minimale Element (min-heap) Auch die Suche ist nicht wirklich schnell Wofür braucht man dann denn überhaupt Heaps? Heaps können gut sortieren (Heapsort) Heaps ergeben gute Priority Queues ( intelligente ToDo-Liste mit den Operationen insert, maximum, extract_max) 11

Heaps Dummerweise will man oft zwei Priority Queues zu einer zusammenfassen Das mag unser binärer Heap allerdings gar nicht (Θ(n)) Binomialheap Ein Binomialheap ist ein Wald von Binomialbäumen, die die Heapeigenschaft erfüllen, wobei jeder Baumgrad im Wald nur einmal vorkommt B 0 B 1 B 2 B 3 B 2 B 1 B 0 Binomialheaps kann man in (log(n)) vereinigen! Leider braucht man häufig noch eine weitere Operation Z.B. speichern viele Graphalgorithmen Kantengewichte in einer Art Priority Queue, wobei jedes Kantengewicht beim besuchen der Kante um 1 dekrementiert wird Wir benötigen ein decrease_key Leider hat decrease_key auf Binomialheaps eine Laufzeit von Θ(log(n)). Wenn wir das für jede Kante eines dichten Graphen aufrufen, haben wir Laufzeit (log( E ) * E ) = (log( V ) * V 2 ) 12

Fibonacci-Heaps Fibonacci-Heaps sind Verwandte der Binomialheaps, unterstützen aber insert, merge und decrease_key in amortisiert konstanter Zeit! eine für die Theorie sehr schöne Datenstruktur (z.b. verwendet von den asymptotisch schnellsten MST- und SSSP Algorithmen) Aber: Hohe Konstanten in der O-Notation versteckt! Implementierung und Funktionsweise gruselig! Graphen Vielleicht die wichtigste und allgemeinste Datenstruktur der Informatik Graphen verbinden Knoten über Kanten miteinander Knoten und Kanten können jeweils Informationen tragen (z.b. Stadtnamen und Entfernungen) 300 km Hamburg 200 km Berlin 200 km 450 km Köln Dresden 200 km 400 km Frankfurt 300 km 50 km 200 km 150 kmmannheim Nürnberg Saarbrücken 100 km 200 km 250 km Stuttgart München 13

Graphen können ungerichtet oder gerichtet sein! v 1 v 1 v 3 v 3 v 2 v 4 v 5 v 6 v 7 v 2 v 4 v 5 v 6 v 7 v 10 v 9 v 8 v 10 v 9 v 8 Ein ungerichteter Graph heißt zusammenhängend (connected), wenn man von jedem Knoten aus jeden anderen Knoten über einen Pfad erreichen kann. v 1 v3 v 2 v 4 v v 6 v 7 v 10 5 v 9 v 8 Sonst zerfällt er in mehrere Zusammenhangskomponenten. v 1 v3 v 2 v 5 v 4 v 10 v 6 v 7 v 9 v 8 14

Ein gerichteter Graph heißt stark zusammenhängend (strongly connected), wenn man für jedes Knotenpaar u und v u von v aus und v von u aus erreichen kann. Sonst zerfällt er in mehrere starke Zusammenhangskomponenten. Durchsuchen von Graphen Sehr häufig will man einen Graphen nach einem Element mit bestimmten Eigenschaften durchsuchen Bsp: In der Künstlichen Intelligenz werden oft die Bewertungen möglicher Züge in einem Spiel in Graphen gespeichert. Der Graph wird dann nach dem Zug mit der höchsten Bewertung durchsucht (z.b. bei Schach, Dame, Tic Tac Toe, ) Die Reihenfolge, in der die Knoten besucht werden, ist häufig von Bedeutung (Bsp: Spielbaum beim Schach: Tiefensuche folgt zuerst einer möglichen Zugkombination bis ans Ende des Spiels ) 15

Breitensuche: ausgehend von einem Knoten v, durchsuche die von ihm erreichbaren Knoten in der Reihenfolge Ihrer Distanz von v v 1. u w 2. Für den Spezialfall eines Baumes gilt also: der Baum wird Ebene für Ebene durchsucht! x y z 3. Tiefensuche: Steige immer so tief wie möglich in den Baum hinab, d.h. folge immer den Kanten des letzten neu entdeckten Knoten. v u w x y 16

Beide Suchverfahren laufen in linearer Zeit in der Anzahl der Kanten und Knoten: ( V + E ) Beide Suchverfahren liefern eine zusätzliche Information: den sogenannten Predecessor-Graphen Im Predecessor-Graphen gibt es eine Kante von u nach v, genau dann wenn wir bei der Suche den Knoten v vom Knoten u aus kommend entdeckt haben! Dieser Graph ist eine wichtige Eingabe für viele darauf aufbauende Graphalgorithmen! Daher ist es häufig nützlich sich daran zu erinnern, welche Informationen er enthält! Beispiele für wichtige Graphalgorithmen: Bestimmen der starken Zusammenhangskomponenten (basiert auf DFS) Topologisches Sortieren (geht auch mittels DFS) Bestimmung des Minimum Spanning Tree; dies ist ein Baum, der alle Knoten eines Graphen verbindet, und für den die Summe der Kantengewichte (geklaut aus dem Originalgraphen) minimal ist Wichtiges Beispiel für einen Greedy-Algorithmus! (läuft immer in Richtung des aktuellen lokalen Optimums) Bestimmen von kürzesten Pfaden, d.h. Pfaden mit minimalen Kantengewichten (SSSP, SDSP usw.) 17