Teil X Grundlegende Datenstrukturen - Lehrveranstaltung ...

Die Seite wird erstellt Nikolai-Stefan Schilling
 
WEITER LESEN
Teil X Grundlegende Datenstrukturen - Lehrveranstaltung ...
Teil X

Grundlegende Datenstrukturen
Überblick

         1        Einführung

         2        Datenstrukturen für Kollektionen

         3        Queues und Stacks

         4        Bäume, Suchbäume und Hash-Tabellen

Eike Schallehn, FIN/ITI                  Grundlagen der Informatik für Ingenieure   498/714
Datenstrukturen

                     Immer wiederkehrende Anforderungen an Verwaltung von
                     Daten im Haupt- und Sekundärspeicher:
                          typische Anordnungen und Zusammenhänge,
                          typische Operationen und
                          immer möglichst effizient!
                     Vergleichbar Algorithmenmustern für die Verarbeitung von
                     Daten: „klassische“ Datenstrukturen als Muster für
                     effiziente Verwaltung von Daten
                     Darüber hinaus: viele klassische Datenstrukturen oft als
                     direkt wiederverwendbare Implementierungen in
                     Programmiersprachenbibliotheken vorhanden

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   499/714
Beispiele für Datenstrukturen und deren
         Verwendung

                     Prüfungslisten mit geordneten Studentendaten
                     Knoten- und Kantenlisten in BREP-Modellen
                     Das Inventory einer Computerspielfigur als Menge von
                     Gegenständen
                     Verzeichnisbäume zur Verwaltung von Dateien
                     Straßennetzwerke eines Routenplaners als Graphen
                     Warteschlangen mit Prozessen für die Prozessverwaltung
                     des Betriebssystems
                     Der Programmstack zur Verwaltung lokaler Daten von
                     Funktionen während der Programmausführung
                     B-Bäume als Indexe für schnelle Zugriffe in
                     Datenbanksystemen (→)

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   500/714
Definition: Datenstrukturen

         Definition (Datenstruktur)
         Eine Datenstruktur ist eine Anordnungsvorschrift zur
         Organisation und Speicherung von Daten, die für bestimmte
         Klassen von Anwendungen einen effizienten Zugriff ermöglicht.
         Umfasst zwei wesentliche Aspekte:
         Schnittstelle: Festlegung der möglichen Operationen und des
                       Verhaltens als abstrakte Spezifikation (Abstrakte
                       Datentypen →) oder konkrete
                       Programmierschnittstelle (z.B. Bibliotheken wie
                       C++ Standard Template Library →)
         Implementierung: konkrete Umsetzung in einer
                     Programmiersprache durch möglichst effiziente
                     Speicherstrukturen und Algorithmen

Eike Schallehn, FIN/ITI             Grundlagen der Informatik für Ingenieure   501/714
Abstrakte Datentypen

                     Abstrakte Datentypen (ADTs) als
                     implementierungsunabhängige Spezifikationmethode der
                     Schnittstelle und der Semantik
                     Beispiel: Menge
                          type Set[Item]
                          operators
                             create: → Set
                             is_empty: Set → Bool
                             insert: Set × Item → Set
                             is_in: Set × Item → Bool
                          axioms ∀s : Set, ∀i,j : Item
                             is_empty (create) = true
                             is_empty (insert (s, i)) = false
                             is_in (create, i) = false
                             is_in (insert (s, i), j) =
                                if i=j then true else is_in (s, j)
                             insert(insert(s,i),j) = insert(insert(s,j),i)
                             insert(insert(s,i),i) = insert(s,i)

Eike Schallehn, FIN/ITI                        Grundlagen der Informatik für Ingenieure   502/714
Eigenschaften von Datenstrukturen

         Datenstrukturen sind ...
          ... komplex: werden durch Typkonstruktoren (mit Zeigern,
                       Feldern, Strukturen, Klassen, etc.) aus
                       einfacheren Strukturen zusammengesetzt und
                       letztendlich auf Basisdatentypen (numerische,
                       alphanumerische) zurückgeführt
         ... dynamisch: können konkrete Ausprägung zur Laufzeit
                      ändern, um zum Beispiel beliebige Anzahl neuer
                      Fakten aufzunehmen oder diese aus der Struktur
                      zu entfernen
         ... wiederverwendbar: erlauben, wenn einmal definiert, den
                      Einsatz für zahlreiche verschiedene Anwendungen

Eike Schallehn, FIN/ITI             Grundlagen der Informatik für Ingenieure   503/714
Datenstrukturen für Kollektionen

                     Kollektionen: Oberbegriff für Datenstrukturen, die eine
                     Sammlung/Anzahl von gleichartigen Objekten verwalten
                     sollen
                          Wichtigste: Mengen, Multimengen, Listen
                     Je nach Anwendung sehr unterschiedliche Anforderungen
                          Duplikate: können (werte-)gleiche Objekte in der Struktur
                          auftreten
                          Ordnung: spielt die Reihenfolge der Elemente in der
                          Struktur eine Rolle
                          Positionaler Zugriff: kann der Zugriff über die Position
                          innerhalb der Struktur erfolgen (vergleichbar Array)
                          Assoziativer Zugriff: kann der Zugriff über einen anderen
                          Wert (Schlüssel) erfolgen
                          Iterativer Zugriff: Durchlaufen aller Elemente in der
                          Kollektion (z.B. mittels Schleife) für alle Strukturen möglich
                     Abgrenzung zum Feld (Array) in Programmiersprachen:
                     Feld ist nicht dynamisch, da feste Anzahl von Elementen
Eike Schallehn, FIN/ITI                       Grundlagen der Informatik für Ingenieure     504/714
Überblick: Kollektionsdatentypen

             Kollektionstyp     Dynamisch              Duplikate                Ordnung   Zugriff
             Array / Feld          nein                   ja                       ja     Position
             Set / Menge            ja                   nein                     nein
             Bag / Multimenge       ja                    ja                      nein
             List / Liste           ja                    ja                       ja     Position
             Map, Hash Table        ja                    ja                      nein    Assoziativ

Eike Schallehn, FIN/ITI              Grundlagen der Informatik für Ingenieure                    505/714
Schnittstellen von Kollektionsdatentypen

                     Zum Teil sehr unterschiedlich nach Implementierung
                     Grundlegende Funktionen für alle Kollektionstypen
                          Erzeugen einer (leeren) Kollektion
                          Suchen eines Elementes
                          Einfügen eines Elementes
                          Löschen eines Elementes
                     Spezielle Funktionen für Listen
                          Element an einer bestimmten Position zurückgeben
                          Einfügen eines Elementes am Anfang, am Ende, an einer
                          bestimmten Position
                          Löschen eines Elementes am Anfang, am Ende, an einer
                          bestimmten Position
                          Sortierung der Liste nach einem bestimmten Kriterium
                     Spezielle Funktionen für Maps/Hash-Tabellen
                          Einfügen eines Elementes mit Zugriffsschlüssel
                          Suchen eines Elementes anhand des Schlüssels
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   506/714
Implementierung von Kollektionen /1

                          Liste

                    Knoten1          Knoten2     Knoten3                                    KnotenN
                     4               17          21                                         37        NULL

                     Grundprinzipien für Mengen, Multimengen, Listen etc.
                     ähnlich
                           1   Verwendung von Klassen oder Strukturen für
                               Kollektions-Schnittstelle sowie innere Knoten
                           2   Verwendung von Zeigern zum Aufbau der dynamischen
                               Struktur aus einzelnen Knoten
                     Einfachste Lösung:
                               Kollektionsobjekt mit Zeiger auf ersten Knoten
                               Knoten trägt Wert und Zeiger auf nächsten Knoten
Eike Schallehn, FIN/ITI                          Grundlagen der Informatik für Ingenieure                    507/714
Implementierung von Kollektionen /2

                          Liste

                    Knoten1       Knoten2   Knoten3                                    KnotenN
                     4            17        21                                         37        NULL

                     Zusätzlicher Zeiger auf letztes Element im Listenkopf
                     Erlaubt Einfügen bzw. Löschen des letzten Elementes mit
                     O(1) statt O(n), da Liste nicht erst komplett durchlaufen
                     werden muss

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure                    508/714
Implementierung von Kollektionen /3

                           Liste

                          Knoten1   Knoten2             Knoten3                          KnotenN
                            4         17                  21                               37      NULL
                  NULL

                     Häufig verwendete Implementierung: doppelt verkettete
                     Liste (Double Linked List) mit „Rückzeigern“ von jedem
                     Knoten auf seinen Vorgänger
                     Erlaubt Durchlaufen und Navigieren in beliebige Richtung
                     Höherer Speicheraufwand

Eike Schallehn, FIN/ITI                       Grundlagen der Informatik für Ingenieure                    509/714
Implementierung von Kollektionen /4

         Zahlreiche Alternativen bei tatsächlichen Implementierung
                     Große Anzahl von Zeigern oft wenig speichereffizient →
                     intern Verwendung von verketteten Arrays
                     Zahlreiche Optimierungen, insbesondere für Suche in Liste
                     (Skip-Listen)
                     Interne Implementierung als Baum (→) oder Hash-Tabelle
                     (→) zur Beschleunigung bestimmter Operationen (zum
                     Beispiel Einfügen in Mengen mit gleichzeitigem Test, ob
                     Element schon in der Menge)
                     ...

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   510/714
Wiederverwendbarkeit für verschiedene
         Elementtypen

                     Kollektionen werden mit immer wieder gleicher
                     Funktionalität für viele verschiedene Anwendungen
                     benötigt, zum Beispiel
                          Liste von ganzen Zahlen
                          Liste von Vertexes in OpenGL
                          Liste von Studenten (Objekte einer Klasse)
                          ...
                     Bisher: Elementtyp in Knoten-Struktur/Klasse festgelegt
                     Keine Wiederverwendbarkeit: muss für jede Anwendung
                     neu programmiert oder angepasst werden
                     Mögliche Lösungen: void-Pointer (in C) bzw. Templates
                     mit Typparametern in C++ (Java, uva.)

Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   511/714
Elemente mittels void*

           class Node {

                   private:
                      void* element;
                      ...
           }

                     Erzeugung einzelner Elemente als separate Objekte auf
                     dem Heap und Referenzierung über untypisierten (void)
                     Zeiger
                     Nachteile:
                          Nicht typsicher: Kollektion kann Elemente beliebigen Typs
                          enthalten → fehleranfällig
                          Erfordert prinzipiell Arbeit mit Zeigern
                     Einzige Option in vielen älteren Programmiersprachen,
                     zum Beispiel C

Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   512/714
Elemente mittels Templates /1

           template 
           class Node {

                   private :
                      T element;
                      ...
           };

           template 
           class List { ... };

                     Typparameter in aktuellen Programmiersprachen
                     (Templates in C++, Generics in Java, Delphi und C#)
                     Erlauben Implementierung generischer
                     „Klassenschablonen“

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   513/714
Elemente mittels Templates /2

                     Typparameter werden bei der Erzeugung einer konkreten
                     Variablen durch einen konkreten Typ ersetzt, zum Beispiel
           List meineListe;

                     Setzt zur Übersetzungszeit T auf int
                     Meist Übersetzung einer separaten Klasse für alle
                     Typparameter
                     Beispiel im folgenden Abschnitt: Warteschlangen (Queues
                     →) mittels Templates
                     In C++: Standard Template Library (STL) setzt
                     wiederverwendbare Kollektionstypen als Templates um →

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   514/714
C++ Standard Template Library (STL)

                     Bietet (vor allem) Kollektionsklassen und einige
                     Standaralgorithmen
                     Kollektionsklassen (Auswahl)
                          list: Liste (geordnet, Duplikate)
                          vector: dynamisches Array, ähnlich Liste
                          set: Menge (ungeordnet, kein Duplikate)
                          multiset: Multimenge (ungeordnet, Duplikate)
                          map: Kollektion mit assoziativem Zugriff (Schlüssel)
                     Iterativer Zugriff (Durchlaufen) von Kollektionen über
                     Iterator-Klassen (→)

Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   515/714
C++ STL: Einfaches Beispiel

           #include 
           #include 
           using namespace std;

           int main() {

                   list zahlenliste;
                   zahlenliste.push_back(7);
                   zahlenliste.push_back(1);
                   zahlenliste.push_back(13);
                   zahlenliste.sort();
                   list::const_iterator position;
                   for (position = zahlenliste.begin();
                         position != zahlenliste.end(); position++)
                      cout
Iteratoren für Kollektionen

                     Ebenfalls grundlegende Datenstruktur: Hilfsstruktur zum
                     Durchlaufen einer Kollektion
                          Daten bestehen nur aus Verweis (Zeiger, Referenz) auf
                          aktuelle Position (z.B. Knoten) in der Kollektion
                          Methoden und Operatoren zum Steuern des Durchlaufs
                          (Anfang, Ende, Weitersetzen, Zurücksetzen, ...)
                     In C++ STL ebenfalls als Template-Klassen umgesetzt
                     Verschiedene Iteratoren möglich
                          Navigationsrichtungen (vor- und rückwärts, nur vorwärts)
                          Modifikation der Kollektion (z.B. Einfügen, Löschen an
                          Position) erlaubt
                          Wahlfreie Positionierung: beliebiges Setzen der Position,
                          Überspringen von Einträgen, etc.

Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   517/714
Zusammenfassung: Kollektionen

                     Verwaltung von Anzahl von Objekten immer
                     wiederkehrendes Problem
                     Unterschiedliche Anforderungen: Duplikate, Ordnung,
                     Zugriffsmöglichkeiten
                     → unterschiedliche Strukturen: Listen, Mengen,
                     Multimengen, Maps
                     → unterschiedliche Implementierungsmöglichkeiten nach
                     Möglichkeiten der Programmiersprache und
                     Anforderungen bzgl. Laufzeit und Speicheraufwand
                     In C++ umgesetzt als Template-Klassen in der STL

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   518/714
Queues und Stacks

                     Beide Datenstrukturen sind Listen (mit eingeschränkter
                     Funktionalität) ähnlich und auch oft vergleichbar
                     implementiert
                     Aber: haben besondere Bedeutung als Zwischenspeicher
                     für die Steuerung der Programmlogik

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   519/714
Queues: Warteschlangen

                          34                                                                  17

                                45       7           22                  13             5
                  Enqueue                                                                   Dequeue

                     FIFO-Prinzip: First In, First Out
                     Entspricht Liste, bei der nur am Anfang geschrieben/eingefügt
                     und am Ende gelesen/entfernt werden kann
                     Zwischenspeicherlösung, welche Daten aufsteigend nach
                     Dauer seit der letzten Bearbeitung bereitstellt: zuerst älteste
                     Daten bearbeiten
                     Zwei wichtige Zugriffsoperationen:
                         enqueue: Einreihen eines Elementes in die Warteschlange
                         dequeue: Auslesen eines Elementes aus der
                         Warteschlange
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure                 520/714
Verwendung von Queues

                     Meist auf Ebene des Betriebsystems oder von Protokollen
                     Synchronisation (Herstellung einer zeitlichen
                     Reihenfolge) von parallelen Zugriffen auf beschränkte
                     Ressourcen
                          Prozesse auf Prozessoren
                          Lese-/Schreibanforderungen auf Festplatten
                          Transfer von Daten in Netzwerken
                          Druckaufträge an einen Drucker
                          Transaktionen in Datenbanksystemen (→)
                          ...
                     Asynchrone Kommunikation: Zwischenspeicherung
                     eingehender Nachrichten/Daten, z.B. Pipe bei
                     Prozeßkommunikation
                     Simulation von Produktions- und Transportprozessen
                     Lastverteilung auf parallel arbeitende Ressourcen über
                     Kontrolle von Warteschlangen, z.B. Prozessoren in
                     Multiprozessormaschinen oder einzelnen Servern in
                     Server Clustern
Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   521/714
Stacks: Stapelspeicher

                     LIFO-Prinzip: Last In, First Out                                           17
                                                                     34
                     Entspricht Liste, bei der nur am
                     Anfang geschrieben/eingefügt                          Push               Pop
                     und ebenda gelesen/entfernt
                     werden kann                                                         47
                     Zwischenspeicherlösung, welche
                     Daten absteigend nach Dauer                                         3
                     seit der letzten Bearbeitung
                     bereitstellt: zuerst aktuellste                                     22
                     Daten bearbeiten
                     Zwei wichtige                                                       5
                     Zugriffsoperationen:
                          push: Ablegen eines
                          Elementes auf dem Stapel
                          pop: Entnehmen eines
                          Elementes vom Stapel
Eike Schallehn, FIN/ITI                       Grundlagen der Informatik für Ingenieure               522/714
Verwendung von Stacks

                     Meist auf Ebene der Speicherverwaltung für Programme
                     Mikroprozessoren unterstützen Stapelspeicher direkt:
                     haben Stack Pointer-Register (Zeiger auf oberstes
                     Stack-Element) und Maschinensprache umfaßt Befehle
                     PUSH und POP
                     Programm-Stack: bei Aufruf von Funktionen oder
                     Sub-Routinen werden aktuelle Daten (Variablen,
                     Programmzustand) auf einem Stack verwaltet
                          Rahmen für Daten eines Funktionsaufrufs: Stack Frame
                          Sequentielle Folge aller Funktionsaufrufe (Stack Frames):
                          Stack Trace
                     Syntaktische Analyse von Ausdrücken oder Sätzen (mit
                     implizit aus Regeln gebildeter hierarchischer Struktur)
                          Parser als Teil von Compilern und Interpretern zur
                          Übersetzung von Programmtext
                          Auswertung algebraischer Terme
                          ...
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   523/714
Queue Implementierung

                     Implementierung einer einfachen Queue mit
                     Basisfunktionalität in C++
                     Verwendet Templates: ermöglicht Wiederverwendung der
                     Queue für verschiedene Elementtypen
                          Queue wi;
                          Queue wc;
                          Queue ws;
                          Queue wsp;
                          ...

                     Implementierung illustriert auch Grundprinzipien für
                     Kollektions-Datenstrukturen in C++ (einfach verkettete
                     Liste)
                     Vollständiger Quelltext auf der Web-Seite zur Vorlesung

Eike Schallehn, FIN/ITI                          Grundlagen der Informatik für Ingenieure   524/714
Queue Implementierung: Knoten-Klasse (C++)

           template 
           class Node {

                   public :
                      Node(T e, Node* n) {
                         element = e;
                         next = n;
                      }
                      void set_next(Node* n) {next = n;}
                      Node* get_next() { return next;}
                      T get_element() { return element;}
                   private :
                      T element;
                      Node* next;
           };

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   525/714
Queue Implementierung: Queue-Klasse (C++)

           template 
           class Queue {

                   public :
                      Queue() {
                         first = NULL;
                         last = NULL;
                      }
                      void enqueue(T element);
                      T dequeue();
                      bool is_empty() {
                         return (first == NULL);
                      }
                   private :
                      Node* first;
                      Node* last;
           };

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   526/714
Queue Implementierung: enqueue() (C++)

           template 
           void Queue::enqueue(T element) {

                   Node* old_last = last;
                   last = new Node(element, NULL);
                   if (old_last == NULL) first = last;
                   else old_last->set_next(last);
           }

                     Einfügen eines Elementes durch Erzeugen eines neuen
                     Knotens am Ende der Warteschlange
                     Spezialfall: Warteschlange war vorher leer

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   527/714
Queue Implementierung: dequeue() (C++)

           template 
           T Queue::dequeue() {
              if (first==NULL)
                 throw ”Dequeue from empty queue.”;
              T e = first->get_element();
              Node* old_first = first;
              first = first->get_next();
              if (first == NULL) last=NULL;
              delete old_first;
              return e;
           }

                     Rückgabe des Elementes im Knoten am Listenanfang und
                     dann Knoten löschen
                     Spezialfall: Warteschlange ist danach leer

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   528/714
Queue Implementierung: main() (C++)

           int main() {

                   Queue w;
                   w.enqueue(19);
                   w.enqueue(1);
                   w.enqueue(42);
                   w.enqueue(13);
                   while (! w.is_empty())
                      cout
Zusammenfassung: Queues und Stacks

                     Queue (Warteschlange) und Stack (Stapel) sind
                     listenähnliche Datenstrukturen
                     Besondere Bedeutung für Steuerung von
                     Programmabläufen
                     Grundprinzipien:
                          Queue: „Daten, die ich jetzt nicht bearbeiten kann, packe
                          ich in eine Warteschlange und arbeite diese dann später
                          systematisch ab“
                          Stack: „Ich bearbeite erstmal die aktuellsten Daten, und
                          packe diese bei noch dringenderen Aufgaben auf den
                          Stapel, von wo ich sie hole, sobald ich mit der aktuellen
                          Aufgabe fertig bin“

Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   530/714
Bäume, Suchbäume und Hash-Tabellen

                     Im folgenden Fokus auf Datenstrukturen, welche den
                     assoziativen Zugriff (über einen bestimmten Wert als
                     Suchkriterium) optimieren
                     Bäume: Abbildung bzw. Vorberechnung von
                     Entscheidungen während der Suche in einer geordneten
                     Menge als hierarchische Datenstruktur
                     (Entscheidungsbaum, Suchbaum)
                     Hash-Tabellen: Abbildung von Objekten auf den Speicher
                     (deren Position darin) wird direkt aus dem Suchkriterium
                     als Eigenschaft der Objekte abgeleitet

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   531/714
Bäume

                     Grundlegende Datenstruktur zur
                     Abbildung einer Hierarchie
                     Setzt Grundprinzip „Teile und
                     Herrsche“ (siehe Algorithmen
                     (→) als Datenstruktur um:
                     Zerlegung von großen
                     Datenmengen in kleinere, besser
                     handhabbare
                     Grundstruktur: ausgehend von
                     einer Wurzel (Gesamtheit)
                     kommt man über verschiedene
                     Verzweigungen (Unterteilungen)
                     zu den Blättern (kleinste
                     Einheiten)

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   532/714
Allgemeine Struktur von Bäumen

                  Höhe des Baumes                                       Wurzel

                          1                                                    Innere Knoten

                          2

                          3

                          4

                                                                               Blätter

Eike Schallehn, FIN/ITI             Grundlagen der Informatik für Ingenieure                   533/714
Beispiele: Baumstrukturen in der Informatik

                     Dateisysteme mit Festplatten, Verzeichnissen, wiederum
                     darin enthaltenen Verzeichnissen und letztendlich Dateien
                     Dokumentenstrukturen, z.B. Mit Kapiteln, Abschnitten,
                     Absätzen
                          HTML und XML als hierarchische Strukturen
                     Syntaktische Analyse und Auswertung von
                     Programmen/Termen: Zerlegung eines Satzes einer
                     Sprache (Grammatik) enstprechend Regeln in
                     Teilausdrücke/Wortgruppen bis hin zu kleinsten Einheiten
                     (Atome, Terminale)
                     Suchbäume als Indexe zum schnellen assoziativen
                     Zugriff über Schlüsselwerte
                          Datenbanksysteme
                          Allgemein: Suche nach Worten in Texten
                          Speziell: Suchmaschinen im World Wide Web

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   534/714
Binäre Suchbäume

                                                12

                                       5                          17

                                   2       11             15                 19

                                                  14                     18            21

                     Binär = Verzweigungsgrad 2: jeder Knoten hat maximal 2
                     Kindknoten
                     Jeder Knoten speichert einen Suchschlüssel und
                     repräsentiert damit folgende Entscheidung:
                          Ist der gesuchte Wert gleich dem Schlüssel → GEFUNDEN
                          Ist der Wert kleiner, gehe zum linken Kindknoten
                          Ist der Wert größer, gehe zum rechten Kindknoten

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure        535/714
Binäre Suchbäume: Suchen und Einfügen

                     Suchen und Einfügen prinzipiell ähnlich:
                          Algorithmus startet an der Wurzel
                          In jedem Knoten: wenn Schlüssel nicht gefunden,
                          verzweige zu einem Kindknoten
                          Auf Blattebene:
                              Einfügen: neuen Kindknoten erzeugen
                              Suchen: Worst Case - Schlüssel nicht gefunden
                     Aufwand für beide Operationen dominiert vom Durchlaufen
                     des Weges von der Wurzel bis zum Blatt, d.h. Höhe des
                     Baumes an dieser Stelle
                     Balancierter Baum (→): Baum ist so gleichmäßig gefüllt,
                     dass Weg von der Wurzel zu Blättern überall möglichst
                     gleich
                     Bei balanciertem Baum mit n = 2k Elementen ist die Höhe
                     des Baumes ca. h = k = log2 n
                     Durchschnittlicher Aufwand für beide Operationen damit:
                     O(log n)
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   536/714
Balancierte Binäre Suchbäume: Aufwand

                                                              Maximale     Höhe
                                                              #Knoten    = Aufwand
                                                           1= 2^1-1          1
                                                           3=2^2-1           2
                                                           7=2^3-1           3
                                                          15=2^4-1           4
                                                          31=2^5-1           5
                                                          63=2^6-1           6
                                                          127=2^7-1          7
                                                          255=2^8-1          8
                                                              511            9
                                                             1023           10
                                                               ...          ...
                                                                n        O(log n)

Eike Schallehn, FIN/ITI    Grundlagen der Informatik für Ingenieure                  537/714
Binärbaum: Beispielimplementierung (C++)

                     Einfach Implementierung bestehend aus Klassen für
                          Knoten mit Schlüssel und Verweisen auf Kindknoten
                          Binärbaum mit Verweis auf Wurzeln
                     Implementiert nur Suchen und Einfügen
                     Eigentliche Daten werden nicht eingetragen, nur Schlüssel
                     vom Typ int
                     Hinweise
                          Verwendet friend-Klassen: umgehen Kapselung, indem
                          befreundete Klassen auf privat-Daten zugreifen können
                          Vollständiger Quelltext auf der Web-Seit zur Vorlesung

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   538/714
Binärbaum: Knotenklasse

           class Node {

                   friend class BinaryTree;

                   private :
                      int key;
                      Node* left;
                      Node* right;

                          Node(int k) { ... }
                          bool search(int k);
                          void insert(int k);
                          void print(int level);
           };

                     Definiert rekursive Methoden zum Einfügen und Suchen →

Eike Schallehn, FIN/ITI                       Grundlagen der Informatik für Ingenieure   539/714
Binärbaum: Baumklasse

           class BinaryTree {

                   public :
                      BinaryTree() {
                         root = NULL;
                      }
                      bool search(int key);
                      void insert(int key);
                      void print();
                   private :
                      Node* root;
           };

                     Methoden zum Einfügen und Suchen als Einstiespunkt für
                     Rekursion ausgehend von der Wurzel

Eike Schallehn, FIN/ITI                   Grundlagen der Informatik für Ingenieure   540/714
Binärbaum: Einfügen

           void Node::insert(int k) {
              if (k==key) return;
              if (kinsert(k);
                 else left = new Node(k);
              if (k>key)
                 if (right != NULL) right->insert(k);
                 else right = new Node(k);
           }

                     Schlüssel vorhanden → Einfügen beenden
                     Andernfalls, falls möglich im linken (neuer Schlüssel
                     kleiner) oder rechten Teilbaum einfügen (neuer Schlüssel
                     größer)
                     Falls kein Kindknoten links oder rechts existiert: neuen
                     Kindknoten mit neuem Schlüssel erzeugen

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   541/714
Entartung von Bäumen

                     Balanciertheit wichtige Eigenschaft von Bäumen: garantiert
                     effiziente Ausführung der Operationen mit O(log n)
                     Ohne weiteres aber keine garantierte Eigenschaft
                     Abhängig zum Beispiel von Einfügereihenfolge
                     Schlechte Einfügereihenfolge kann zu Entartung des
                     Baumes führen
                     Im schlimmsten Fall wird Baum zu Liste
                     Operationen dann mit wesentlich schlechterer
                     Laufzeitkomplexität O(n): sequentielle Suche

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   542/714
Beispiel: Entartung von Bäumen

                                  4                                 1
                                                                                   2
                          2               6
                                                                                             3
                                                                                                 4
              1               3       5       7
                                                                                                     5
                                                                                                         6
                   Balancierter Baum                                Entarteter Baum                          7
                   bei Einfügereihenfolge                           bei Einfügereihenfolge
                   4, 2, 6, 3, 1, 7, 5                              1, 2, 3, 4, 5, 6, 7

Eike Schallehn, FIN/ITI                           Grundlagen der Informatik für Ingenieure                       543/714
Balancierte Bäume

                     Sicherstellung einer relativen Ausgeglichenheit bei binären
                     Bäumen durch spezielle Modifikationsoperationen
                     (Einfügen, Löschen)
                          Angabe eines speziellen Balancekriteriums, z.B.
                          AVL-Baum: in jedem Knoten darf der Höhenunterschied
                          zwischen linkem und rechten Teilbaum maximal 1 sein!
                          Wird Balancekriterium verletzt, werden Verfahren zur
                          lokalen Reorganisation des Baumes angewandt
                     → AVL-Bäume, Rot-Schwarz-Bäume
                     Vollständige Ausgeglichenheit möglich durch Knoten mit
                     variablem Verzweigungsgrad
                          Mehr als 1 Schlüssel pro Knoten
                          Verweis auf Kindknoten mit Werten zwischen 2 Schlüsseln
                          (Bereich)
                          Knotengröße kann an Speicherstrukturen angepasst
                          werden (z.B. Blöcke der Festplatte)
                     → B-Bäume
Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   544/714
... geht es besser als O(log n)?

                     Assoziative Zugriffe (Suche über einen Schlüsselwert) mit
                     Bäumen mit logarithmischem Aufwand O(log n)
                     D.h. nur ein zusätzlicher Suchschritt notwendige für jede
                     Verdopplung der Größe der Datenmenge, in der gesucht
                     wird
                     Geht es noch besser?
                     Ja, Hash-Tabellen können Schlüsselzugriff (unter
                     bestimmten Bedingungen) mit konstantem Aufwand O(1)
                     umsetzen
                     D.h. egal wie groß die Datenmenge, das Finden der
                     richtigen Daten geht immer gleich schnell!

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   545/714
Hash-Tabellen

                     Auch Streuwerttabelle oder Hash Map
                     Grundprinzip: Berechnung der Position der Daten im
                     Speicher (strukturiert als Tabelle) aus dem Schlüsselwert
                     key
                          Berechnung der Position beim Einfügen
                          Berechnung der Position beim Suchen
                     Erfordert Vorreservierung eines Speicherbereichs der
                     Größe M → M meist sehr groß, ab mehreren Tausend
                     Einträgen
                     Positionen 0 . . . M − 1 in Speicherbereich werden auch
                     Hash Buckets genannte
                     Berechnung der Position über spezielle Hash-Funktion
                                   h : dom(key) → {0, 1, . . . , M − 1}
                     Wahlfreier Zugriff im RAM und auf Festplatte ermöglicht
                     direkten Zugriff auf an dieser Stelle gespeicherte Daten
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   546/714
Einfügen in Hash-Tabellen

                  Zu speichernde                                                       Hash-Tabelle
                      Objekte

                                                                         0          156324, Max Müller
             Student Udo Urban
             MatrNr 170480                                               1
                                                                         2          170480, Udo Urban
             Student Eva Lange
             MatrNr 175783                                               3
                                                                         4
             Student Max Müller                                          5
             MatrNr 156324
                                                                         6          175783, Eva Lange

                                        Hash-Funktion
                                   h(MatrNr)=MatrNr % 7

Eike Schallehn, FIN/ITI                  Grundlagen der Informatik für Ingenieure                        547/714
Suchen in Hash-Tabellen

                                                                               Hash-Tabelle

                                                                 0         156324, Max Müller
            Suche nach                                           1
           Matrikelnummer:                                                 170480, Udo Urban
                                                                 2
                   170480                                        3
                                                                 4
                                                                 5
                                                                 6         175783, Eva Lange

                                  Hash-Funktion
                             h(MatrNr)=MatrNr % 7

Eike Schallehn, FIN/ITI             Grundlagen der Informatik für Ingenieure                    548/714
Hash-Funktionen

                     Wertebereich ist (beim hier betrachteten statischen
                     Hashen) durch Speichergröße M bestimmt
                     Problem: Hash-Funktion ist nicht injektiv, d.h.
                     verschiedene Schlüssel können auf eine Adresse
                     abgebildet werden → Kollisionen!
                     Gute Hash-Funktionen erzeugen möglichst zufällig
                     gestreute Speicherzuordnung und machen dadurch
                     Kollisionen unwahrscheinlich
                     Meist umgesetzt durch
                          Kombination von verschiedenen Operationen mit möglichst
                          zufälligem Ergebnis, z.B. Bit-Verschiebeoperationen
                          Am Ende Modulodivision durch M → Rest ist Hash-Wert
                          Primzahlen als Parameter der Hash-Funktion sorgen für
                          gute, zufällige Verteilung
                     Kollisionen lassen sich aber meist nicht völlig vermeiden →
                     erfordern Kollisionsbehandlung
Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   549/714
Hash-Tabellen: Kollisionsbehandlung

         Verkettete Liste: der Eintrag in einer Hash-Tabelle verweist auf
                      eine Liste der dorthin gehashten Daten
                           Kann bei schlechter Hash-Funktion mit vielen
                           Kollisionen zu Entartung führen
                           Mehraufwand für Speicherung
           Sondieren: (engl. Probing) ist der Hash Bucket bereits belegt,
                      wird nach einem einfachen Muster ein anderer
                      Platz gesucht
                           Z.B. lineares Sondieren: testen ob folgende
                           Hash Bucket frei ist, erster freier wird genutzt
         Doppeltes Hashen: ist der Hash Bucket belegt, wird (ggf.
                    wiederholt) ein weiterer Hash-Wert berechnet und
                    diese Position getestet

Eike Schallehn, FIN/ITI               Grundlagen der Informatik für Ingenieure   550/714
Implementierung von Hash-Tabellen

                     (Bisher besprochene) statische Hash-Verfahren:
                     vordefinierte Speichergröße kann effizient über Array
                     umgesetzt werden
                     Dynamische Hash-Verfahren können den benutzten
                     Speicherbereich zur Laufzeit Vergrößern → z.B. durch
                     verkettete Arrays
                     Kollisionsbehandlung durch verkettet Liste erfordert
                     zusätzliche Datenstruktur
                     Sondieren und Doppeltes Hashen Erfordern aufwändigere
                     Operationsimplementierungen
                     Beispielimplementierung auf der Web-Seite zur Vorlesung
                          Einfaches statisches Hashverfahren mit linearem Sondieren
                          In der Vorlesung nicht vorgestellt

Eike Schallehn, FIN/ITI                     Grundlagen der Informatik für Ingenieure   551/714
Nachteile von Hashtabellen

                     Keine Ordnung der Elemente: in Bäumen sind Elemente stets
                     geordnet gespeichert – geordnete Ausgabe aus einer
                     Hash-Tabelle erfordert zusätzliche Sortierung
                     Vorreservierung des Speichers notwendig: z.B. über Arrays,
                     die zur Vermeidung von Überlauf und Kollisionen ggf. weit
                     überdimensioniert sind (Trade-off: Speichereffizienz vs.
                     Laufzeiteffizienz)
                     Überlauf möglich: bei einigen statischen Verfahren (z.B. bei
                     Überlaufbehandlung durch Sondieren, nicht bei verketteter Liste)
                     kann die Hash-Tabelle tatsächlich vollständig gefüllt werden, so
                     dass keine weiteren Daten eingetragen werden können
                     Aufwand für Dynamik: Verfahren, welche zur Vermeidung von
                     Überläufen und Kollisionen, die Hash-Tabelle dynamisch
                     wachsen lassen, nähern sich mit ihrem Laufzeitverhalten
                     Bäumen an
                     Aufwand für Überlaufbehandlung: auch bei vielen Kollisionen,
                     z.B. durch schlechte Hash-Funktion, verschlechtert sich die
                     Laufzeitkomplexität
Eike Schallehn, FIN/ITI                      Grundlagen der Informatik für Ingenieure   552/714
Zusammenfassung: Datenstrukturen

                     Klassische Datenstrukturen bieten Standardlösungen für
                     effiziente Bearbeitung von Daten
                     Wichtigste hier vorgestellt:
                          Kollektionsdatentypen wie Listen, Mengen und
                          Multimengen zur Verwaltung einer Sammlung
                          zusammengehörender Objekte
                          Queues und Stacks zur Steuerung der
                          Berabeitungsreihenfolge von Datenobjekten
                          Bäume und Hash-Tabellen für schnelles Suchen von
                          Daten über einen Schlüsselwert
                     Oft in Form von generischen Klassenbibliotheken
                     umgesetzt, z.B. STL in C++
                     Eigene Implementierung durch Verwendung von
                     Typkonstruktoren (Arrays, Structs, Klassen) und Zeiger
                     sowie Klassenschablonen (Templates, Generics) möglich

Eike Schallehn, FIN/ITI                    Grundlagen der Informatik für Ingenieure   553/714
Sie können auch lesen