Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

22.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure.

Ähnliche Präsentationen


Präsentation zum Thema: "22.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure."—  Präsentation transkript:

1 22.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 dittrich@cs.uni-dortmund.de EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure II Prof. Dr. Gisbert Dittrich

2 18-2 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Gliederung Hashing das Problem: Alternatives Suchverfahren – bisheriges Vorgehen – geänderte Randbedingungen --> die Idee die Lösung ein Beispiel: Intliste – deren Implementierung Hash1: festverdrahtete Hashfunktion Hash2: rein virtuelle Hashfunktion

3 18-3 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Suchen Erinnerung: Suche mit binären Suchbäumen Ein binärer Suchbaum ist ein binärer Baum, dessen Knoten mit z.B. ganzen Zahlen gefüllt sind, so daß gilt: – linker und rechter Unterbaum sind binäre Suchbäume, – die Beschriftung der Wurzel ist größer als die Beschriftung der Wurzel des linken, kleiner als die Beschriftung des rechten Unterbaums.

4 18-4 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Binäre Suchbäume: Suchen 17 436 28 6 7 1940 Suche nach dem Element 5 Suche nach dem Element 19

5 18-5 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Warum ein neues Suchverfahren? Voraussetzung für Binäre Suchbäume: (totale) Ordnung auf der Nutzinformation Ordnung nicht immer kanonisch verfügbar: Beispiele: – komplexe Zahlen, – Einträge in einer Datenbank (Kundendaten etc.). Also: Alternativen notwendig.

6 18-6 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Idee Es geht immer: Suchen in einer Menge U – z. B. realisiert über verkettete Liste Variation dieser Idee: Suchen in einer Menge von Teilmengen (disjunkt) – 1.Schritt: Bestimme (Teil)-Menge, in der zu suchen ist. – 2. Schritt: Durchsuche diese Menge nach gegebenem Element Randbedingung: – Möglichst gleich große Teilmengen.

7 18-7 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Idee Fortsetzung Formaler: Sei U die (endliche) Menge aller Objekte, für die die Suchoperationen definiert werden sollen. h: U -> {0,..., m-1} sei eine Funktion. U: Menge aller Elemente, die bereits verarbeitet sind. U(j) := h -1 (j) U : Menge aller Elemente in U, die von h auf j abgebildet werden. Aufgabe: t U schon in U ?

8 18-8 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Idee Fortsetzung Schritte zur Lösung der Aufgabe: – Berechne h(t), – sieh nach, ob t ein Element von U(h(t)) ist. Also : Statt ganz U zu durchsuchen, durchsuche nur einen Teil, nämlich U(h(t)). h heißt Hashfunktion – to hash: mischen, zerhacken. – h erfülle: die U(j) sollten etwa gleich groß sein. Repräsentation? Jede Teilmenge U(j) als verkettete Liste U als Feld verketteter Listen

9 18-9 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Idee Fortsetzung 0 1 2 3 4 Listen ein Feld

10 18-10 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Was ist zu tun? Wähle Universum Hier: (zunächst ganze) Zahlen Formulierung von Listen ganzer Zahlen (Datentyp IntListe, (erneute) Wiederholung). Datentyp HashTafel auf der Grundlage von IntListe. Kritisch: Hashfunktion. Wird gleich betrachtet.

11 18-11 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Der Datentyp IntListe int Element; // Element der Liste; Nutzinformation IntListenEl * weiter ; /* Verkettung: Zeiger auf das nächste Element */ Zunächst: IntListenEl(ement) void NutzinfoDruck(){ cout << Element;}; Attribute: Methode: Nutzinfoweiter

12 18-12 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing IntListe Attribut: IntListenEl * DieIntListe; Methoden: IntListe() //Konstruktor IntListe(int r) //Konstruktor bool Testen(int r) void Entfernen(int r) void Einfuegen(int r) void Druck()

13 18-13 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Hilfsmethoden: bool IstDa(IntListenEl *, int) /* IstDa (Liste, r) überprüft (rekursiv), ob das Element r in der Liste Liste bereits vorhanden ist */ IntListenEl * WegDamit (IntListenEL *,int) /* WegDamit(Liste, r) entfernt das Element r aus der Liste Liste und gibt einen Zeiger auf die modifizierte Liste zurück*/ IntListe

14 18-14 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Der Datentyp IntListe (Forts.) Hilfsmethode: void ListenDruck(IntListe *); /* ListenDruck(Liste) druckt die Liste Liste aus; durch einen rekursiven Durchlauf.*/ Hilfsfunktionen --> private/protected

15 18-15 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Der Datentyp IntListe (Forts.) IntListe() { DieIntListe = NULL; } IntListe(int r) { DieIntListe = new IntListenEl; DieIntListe -> Element = r; DieIntListe -> weiter = NULL; } Zwei Konstruktoren:

16 18-16 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Ausgewählte Methoden bool Testen(int r) { return IstDa(DieIntListe, r);} void Entfernen(int r) { DieIntListe = WegDamit(DieIntListe, r);} void Einfuegen(int); void Druck(){ ListenDruck(DieIntListe);} Methoden inline formulierbar Ausnahme: Einfuegen.

17 18-17 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Ausgewählte Methoden: IstDa bool IntListe::IstDa(IntListenEl * Liste, int r) { if (Liste == NULL) return false; else { if (Liste->Element == r) return true; else return IstDa(Liste->weiter, r); } }

18 18-18 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Ausgewählte Methoden: WegDamit IntListenEl * IntListe::WegDamit (IntListenEl * Liste, int r) { if (Liste == NULL) return Liste; else { if (Liste->Element == r) return Liste->weiter; else { Liste->weiter = WegDamit(Liste->weiter, r); return Liste; }}}

19 18-19 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Ausgewählte Methoden: Einfuegen void IntListe::Einfuegen(int r) { if(!Testen(r)) { IntListenEl * neu = new IntListenEl; neu->Element = r; neu->weiter = DieIntListe; DieIntListe = neu; } }

20 18-20 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Ausgewählte Methoden ListenDruck void IntListe::ListenDruck(IntListenEl * Liste) { static int t = 1; if (Liste != NULL) { Liste->NutzinfoDruck ();// Verbindung cout << (t++%8==0 ? "\n" : "\t"); ListenDruck(Liste->weiter); } else { t = 1; cout << "(Ende)" << endl; } } // Nur harter Kern dieser Methode !!

21 18-21 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Hashing Sei t U. Aufgaben Speichere t – Element t wird in der Liste zu h(t) abgespeichert. Suche t – Schaue in der Liste zu h(t) nach und suche dort. Lösche t – Lösche t in der Liste zu h(t).

22 18-22 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Hashing (Forts.) Zentral: Hashfunktion h Muß einfach zu berechnen sein Sollte die Elemente gleichmäßig verteilen. Setze h(x) = x%m, wobei m die Anzahl der einzelnen Listen. Die Listen heißen Konfliktlisten (clash lists) oder Körbe (buckets).

23 18-23 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Vereinbarung Die Datenstruktur heißt Hashtafel. Vereinbare also (m sei gegeben) die Hashtafel als Feld mit m verketteten Listen vom Typ IntListe, definiere Operationen darauf.

24 18-24 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Der ADT HashTafel hT sei ein Feld aus m verketteten Listen. Merke mir in der Variablen maxBucket die Größe m des Feldes. Die Größe der Hashtafel (also von hT ) soll erst zur Laufzeit festgelegt werden können.

25 18-25 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Der ADT HashTafel (Forts.) Operationen für das Element t U: Überprüfen, ob t in der Hashtafel vorhanden ist: Aufruf von hT[h(t)].Testen(t)(. oder -> ??) Einfügen: Füge t ein, indem ich hT[h(t)].Einfuegen(t) aufrufe, falls das Element t nicht in der Tafel ist Entfernen: Entferne t durch Aufruf von hT[h(t)].Entfernen(t).

26 18-26 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Die Klasse HashTafel Für jeden Eintrag hT[j] in der Tafel gilt: hT[j] ist ein Zeiger auf IntListe, also: IntListe * hT[j] Damit Vereinbarung: IntListe ** hT. Allokation einer Tafel mit m Elementen: hT = new IntListe * [m] Nach der Allokation der Tafel: Allokation der einzelnen Elemente, also: for (int i = 0; i < m; i++) hT[i] = new IntListe();

27 18-27 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Die Klasse HashTafel (Forts.) class HashTafel { private: IntListe ** hT; int maxBucket; public: HashTafel(int); int h(int r){return r%maxBucket;} int Testen(int r) {return hT[h(r)]->Testen(r);} void Einfuegen(int r) {hT[h(r)]->Einfuegen(r);} void Entfernen(int r) {hT[h(r)]->Entfernen(r);} void Druck(); };

28 18-28 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Muß noch weiter diskutieren: Konstruktor Methode Druck (stützt sich vollständig auf die entsprechende Methode für IntListe ab). Die Klasse HashTafel (Forts.)

29 18-29 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Die Klasse HashTafel (Konstruktor; Druck ) HashTafel::HashTafel(int m) { maxBucket = m; hT = new IntListe *[m]; for (int i = 0; i < m; i++) hT[i] = new IntListe(); } void HashTafel::Druck() { int i; for (i = 0; i < maxBucket; i++) { cout << "\nBucket für i = " << i << ":\n"; hT[i]->Druck(); }} // Harter Kern der Methode

30 18-30 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Beispielprogramm int main() { int maxAnzahl = 17; int Treffer = 0; int j; HashTafel * dieTafel = new HashTafel(maxAnzahl); for (int i = 0; i < 2000; i++) { j=rand(); if (dieTafel->Testen(j) == true) Treffer++; dieTafel->Einfuegen(j); } cout << "Anzahl der Treffer: " << Treffer << endl; cout << "Durchlauf durch die Tafeln\n"; dieTafel->Druck(); // + zusätzl. Ausdruck !! return 0;} Hash 1

31 18-31 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 1 // alt: hash1 von Doberkat, EINI II, SS 99 // von GD+ JW angepaßt #include #include // nötig für rand() int GesamtAnzahlEintraege = 0; class IntListenEl { public: int Element; IntListenEl * weiter; void NutzinfoDruck(){ cout << Element; };};

32 18-32 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 2 class IntListe { protected: IntListenEl * DieIntListe; bool IstDa(IntListenEl *, int); /* Testet, daß der int-Wert in der Liste von IntListenEl enthalten ist*/ IntListenEl * WegDamit (IntListenEl *, int); /* Entfernt das Listenelement mit dem Eintrag int-Wert aus der Liste von IntListenEl., sofern vorhanden */ void ListenDruck(IntListenEl *); public: IntListe() {DieIntListe = NULL;} IntListe(int r) { DieIntListe = new IntListenEl; DieIntListe -> Element = r; DieIntListe -> weiter = NULL;}

33 18-33 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 3 public:// Fortsetzung... bool Testen(int r) { return IstDa(DieIntListe, r);} void Entfernen(int r) { DieIntListe = WegDamit(DieIntListe, r);} void Einfuegen(int); void Druck(){ListenDruck(DieIntListe);} }; bool IntListe::IstDa(IntListenEl * Liste, int r) { if (Liste == NULL) return false; else {if (Liste->Element == r) return true; else return IstDa(Liste->weiter, r); }}

34 18-34 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 4 IntListenEl * IntListe:: WegDamit(IntListenEl * Liste, int r) { if (Liste == NULL) return Liste; else {if (Liste->Element == r) return Liste->weiter; else { Liste->weiter = WegDamit(Liste->weiter, r); return Liste;}}} void IntListe::Einfuegen(int r) { if(!Testen(r)) { IntListenEl * neu = new IntListenEl; neu->Element = r; neu->weiter = DieIntListe; DieIntListe = neu;}}

35 18-35 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 5 void IntListe::ListenDruck(IntListenEl * Liste) { static int t = 1, AnzEintraege = 0; if (Liste != NULL) { Liste->NutzinfoDruck(); cout << (t++%8==0 ? "\n" : "\t"); AnzEintraege++; ListenDruck(Liste->weiter);} else { t = 1; cout << endl<< "Anzahl der Einträge: \t" << AnzEintraege << " (Ende)" << endl; GesamtAnzahlEintraege += AnzEintraege; AnzEintraege = 0; } Zurück Zu Hash 2

36 18-36 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 6 class HashTafel { private: IntListe ** hT; int maxBucket; public: HashTafel(int); int h(int r){return r%maxBucket;} int Testen(int r) {return hT[h(r)]->Testen(r);} void Einfuegen(int r) {hT[h(r)]->Einfuegen(r);} void Entfernen(int r){hT[h(r)]->Entfernen(r);} void Druck();}; HashTafel::HashTafel(int m) { maxBucket = m; hT = new IntListe *[m]; for (int i = 0; i < m; i++) hT[i] = new IntListe();}

37 18-37 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 7 void HashTafel::Druck() { int i; for (i = 0; i < maxBucket; i++) { char jn = 'j'; if (i > 0) { cout << "\nweiter? (j = ja): "; cin >> jn; } if (jn != 'j') { cout << "Ciao" << endl; break; } cout << "\nBucket für i = " << i << ":\n"; hT[i]->Druck();} }

38 18-38 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Implementierung Hash 1 // Hashing von Integern über IntListen, 8 int main() { int maxAnzahl = 17; int Treffer = 0; int j; HashTafel * dieTafel = new HashTafel(maxAnzahl); for (int i = 0; i < 2000; i++) { j=rand(); if (dieTafel->Testen(j) == true) Treffer++; dieTafel->Einfuegen(j);} cout << "Anzahl der Treffer: " << Treffer << endl; cout << "Durchlauf durch die Tafeln\n"; dieTafel->Druck(); cout << " Insgesamt verarbeitete Einträge:\t" << GesamtAnzahlEintraege; return 0;}

39 18-39 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Beispielprogramm Treffer: 71. Bedeutet: Bei 2000 erzeugten Zufallszahlen werden 71 doppelt erzeugt. Statistik: Mißt die Längen der einzelnen Listen

40 18-40 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Statistik

41 18-41 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Rein virtuelle Hashfunktion eröffnet Parametrisierung derselben: Sei IntListe wie in Hash 1. Verallgemeinerung class AbstrakteHashTafel { private: IntListe ** hT; protected: int maxBucket; // nötig für Unterklassen public: AbstrakteHashTafel(int); virtual int h(int) = 0; // Rest wie vorhin };

42 18-42 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing verhindere arithmetischen Überlauf Neue Hash-Funktion class NeueHashTafel : public AbstrakteHashTafel { public: NeueHashTafel(int m) : AbstrakteHashTafel(m) {} int h(int); }; int NeueHashTafel::h(int r) { long int rl = (long int) r; long int l = rl * rl; long int maxx = (long int) maxBucket; return l % maxx; } Hash2 cast

43 18-43 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 1 // Die ersten Zeilen überein mit Hash 1 Vgl. dazu Hash 1, Seite 1 - Seite 5 class AbstrakteHashTafel { private: IntListe ** hT; protected: // wohl nötig, um int maxBucket; // Unterklassen zu bilden public: AbstrakteHashTafel(int); virtual int h(int) = 0; // erst in Unterklassen zu definieren Implementierung Hash 2 Zurück Zu Hash 1

44 18-44 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 2 // public Fortsetzung: int Testen(int r) {return hT[h(r)]->Testen(r);} void Einfuegen(int r) {hT[h(r)]->Einfuegen(r);} void Entfernen(int r){hT[h(r)]->Entfernen(r);} void Druck(); }; AbstrakteHashTafel::AbstrakteHashTafel(int m) { maxBucket = m; hT = new IntListe *[m]; for (int i = 0; i < m; i++) hT[i] = new IntListe(); } Implementierung Hash 2

45 18-45 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 3 void AbstrakteHashTafel::Druck() { int i; for (i = 0; i < maxBucket; i++) { char jn = 'j'; if (i > 0) { cout << "\nweiter? (j = ja): "; cin >> jn;} if (jn != 'j') { cout << "Ciao" << endl; break;} cout << "\nBucket für i = " << i << ":\n"; hT[i]->Druck();}} Implementierung Hash 2

46 18-46 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 4 class NeueHashTafel : public AbstrakteHashTafel { public: NeueHashTafel(int m) : AbstrakteHashTafel(m) {} int h(int); }; int NeueHashTafel::h(int r) { long int rl = (long int) r; long int l = rl * rl; long int maxx = (long int) maxBucket; return l % maxx; } Implementierung Hash 2

47 18-47 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 5 int main() { NeueHashTafel * dieTafel = new NeueHashTafel(17); int j; int Treffer = 0; for (int i = 0; i < 2000; i++) { j = rand(); if (dieTafel->Testen(j) == true) Treffer++; dieTafel->Einfuegen(j); } Implementierung Hash 2

48 18-48 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing // Abstrakt formuliertes Hashing, 6 // int main() Fortsetzung cout << "Anzahl der Treffer: " << Treffer << endl; cout << "Durchlauf durch die Tafeln\n"; dieTafel->Druck(); cout << " Insgesamt verarbeitete" << "Einträge:\t" << GesamtAnzahlEintraege; return 0; } Implementierung Hash 2 Hash2

49 18-49 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Messung Oh!

50 18-50 Prof. Dr. G. Dittrich 22.05.2000 EINI II Kap. 18: Hashing Was lernen wir daraus? Die Hash-Funktion ist verantwortlich für die Länge der einzelnen Listen. Je länger die Listen sind, desto länger sind die Suchzeiten, desto schlechter kann also das Verfahren insgesamt sein Extremfall: nur eine Liste, – dann hat sich der Aufwand nicht gelohnt.


Herunterladen ppt "22.05.2000 Universität Dortmund, Lehrstuhl Informatik 1 EINI II Einführung in die Informatik für Naturwissenschaftler und Ingenieure."

Ähnliche Präsentationen


Google-Anzeigen