1 / 77

Ziel 1

Ziel 1. Weitere Beiträge zur Wiederverwendbarkeit von Code --> Einführung an Beispielen. Frage: Wie kann man das Hashen von Integern für das Hashen von - komplexen Zahlen - Wörtern - Beschäftigten - ... effizient verwenden?. Ziel 2. Antwort:

jane
Download Presentation

Ziel 1

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ziel 1 • Weitere Beiträge zur Wiederverwendbarkeit von Code --> Einführung an Beispielen. • Frage: Wie kann man das Hashen von Integern für das Hashen von - komplexen Zahlen - Wörtern - Beschäftigten - ... effizient verwenden?

  2. Ziel 2 • Antwort: • Verwendung von Templates/Schablonen (bedeutet: • Klassen können als Parameter in Klassen (-schablonen) zur Erzeugung von Klassen verwendet werden.) Durchgeführt für Beispiele.

  3. Gliederung 1 • Neuer Anwendungsbereich • Klasse komplexe Zahlen • Einführung in Templates/Schablonen 1. Am Beispiel (einfache) Liste: • Schablone für (einfache) Liste. • Beispielanwendungen: • Einfache Liste für komplexe Zahlen • Einfache Liste für Integer • Einfache Liste für Beschäftigte • Konsequenzen • Detail: Erzeugung anonymer Klassen

  4. Gliederung 2 2. Beispiel: Hashing allgemein • Annahmen • Liste(nschablone) • Schablone Hashtafel • Vergleich : int <---> Nutzinfo * • Methoden dazu • Beispielanwendungen: • Hashing für komplexe Zahlen • Hashing für Integer • Hashing für Wörter • Hashing für Beschäftigte nach Klassenzugehörigkeit • Hashing für Beschäftigte nach Verdienststufe

  5. Klasse: KomplexeZahl class KomplexeZahl { private: int Re, Im; public: KomplexeZahl (int r, int i) { Re = r; Im = i;} KomplexeZahl * Plus (KomplexeZahl * p); KomplexeZahl * Minus (KomplexeZahl * p); KomplexeZahl * Minus (); KomplexeZahl * Mal (KomplexeZahl * p); void Druck(); bool Gleich (KomplexeZahl * p); }; Liste kompl Zahlen

  6. Komplexe Zahlen • Deute (a, b) als a + i*b. • Operationen sind dann klar. • Beispiel: Multiplikation, Methode Mal KomplexeZahl * Mal (KomplexeZahl * p) { int r, i; r = Re * p->Re - Im * p->Im; i = Im * p->Re + Re * p->Im; return new KomplexeZahl(r, i);} [(a+ib)*(c+id) = (ac-bd) + i(ad + bc) ; ]

  7. Nun aber • Suchverfahren für komplexe Zahlen. • Binäre Suchbäume: nicht möglich, denn • auf der Menge der komplexen Zahlen ist keine Ordnung (direkt) definiert.

  8. Nun aber (Forts.) • Hashing: im Prinzip möglich • Muß also: • Klasse KomplexList zur Formulierung verketteter Listen für komplexe Zahlen definieren, • das Hashing-Verfahren anpassen. • Das ist LANGWEILIG, da i.w. Gleichförmiges wiederholt wird. • Alternative ? --> Klassen als Parameter

  9. Integer_Hashing: Analyse 1 • class IntListenEl { • public: • int Element; • IntListenEl * weiter; • void NutzinfoDruck()}; • class IntListe { • protected: • IntListenEl * DieIntListe; • bool IstDa(IntListenEl *, int); • IntListenEl * WegDamit (IntListenEl *, int); • void DieserDruck(IntListenEl *);

  10. Integer_Hashing: Analyse 2 • // class IntListe Fortsetzung • public: • IntListe() • IntListe(int r) • bool Testen(int r) • void Entfernen(int r) • void Einfuegen(int) • void Druck()}; • .... • bool IntListe::IstDa(IntListenEl * Liste, int r) { • ....... • else { if (Liste->Element == r) Gleichheit???!!! • ........ Int-Hash: Analyse 3

  11. Analyseergebnis • Analyse der Rolle der int-Größe (vorige Folien) • Ganze Zahlen gehen bei der KlasseIntListenur insofern ein, als • die Komponente Element vom Typint war, • beim Testen die Gleichheit ganzer Zahlen benutzt wurde • sie als Parameter in Methoden auftreten --> Diese Stellen müssen bei einer abstrakteren Behandlung ("Parametrisierung") auf Änderung überprüft werden.

  12. Aufgabe: Abstrakte Formulierung • Listentyp definieren, der diese beiden Angaben (Typ, Gleichheit) als Parameter hat: • ganze Zahlen als Typparameter, • die Gleichheit als Funktionsparameter (Das geht mit Hilfe rein virtueller Funktionen. Wird zunächst zurückgestellt).

  13. Dazu zu erledigen: • Allgemeine Angaben zu Liste: • Annahme über den Typ der Listenelemente, • Angabe der Signaturen von Listenmethoden, • Angabe • der Implementierung, soweit das möglich ist • der typspezifischen Eigenschaften oder Operationen. • Formulierung in C++ • [Zunächst Reduktion auf Liste_einfach: • Initialisieren der Liste - Einfügen eines Elements • Drucken der Liste(nelemente) ]

  14. Nutzinfo weiter Erste Formulierungen • Annahme: • Der Typ der Listenelemente ist Zeiger auf Nutzinfo, wobei Nutzinfo beliebige Klasse. • Grundtyp also: Nutzinfo *. Nutzinfo • class ListenEl { • Nutzinfo * Element; • ListenEl * weiter; • void NutzinfoDruck(){ • Element->Druck(); cout << endl;}}; Element Achtung: Setzt Methode Druck() in Nutzinfo voraus !!!

  15. Erste Formulierungen 2 • class Liste { • ListenEl * DieListe; • void ListenDruck(ListenEl *); • Liste() { • DieListe = NULL;}; • void Einfuegen(Nutzinfo *); • void Druck(){ListenDruck(DieListe);}

  16. Fazit • Fast alle Operationen ohne Kenntnisse des zugrundeliegenden Typs Nutzinfo formulierbar. • Ausnahmen: • der Druck eines Elements • evtl: Gleichheit von Elementen (hier (noch) nicht betrachtet) • Im folgenden: Formulierung als Klasse

  17. Formulierung als Klasse 1 • Dazu auch berücksichtigen: • Angabe, daß der Typ eine Art Parameter der Listenklasse ist !! • Zugriffsspezifikationen (private, protected, public) • Methoden müssen ausformuliert werden

  18. Erste Formulierungen (Ausschnitt) class ListenEl { • Nutzinfo * Element; • ListenEl * weiter; • void NutzinfoDruck(){ • Element->Druck(); • cout << endl; • } • };

  19. Das ist neu Formulierung als Klasse 2 template <class Nutzinfo> • class ListenEl { • public: • Nutzinfo * Element; • ListenEl * weiter; • void NutzinfoDruck(){ • Element->Druck(); • cout << endl; • } • };

  20. Anmerkungen • Durch template <class Nutzinfo >wird angekündigt, daß die folgende Konstruktion eine Klasse Nutzinfo als Parameter hat. • Die nun folgende Klasse ist keine: • Sie ist vielmehr das Muster (oder die Schablone) einer Klasse. Aus der Schablone können dann Klassen erzeugt werden (Wie, werden wir gleich sehen). • Schablonen können im Hinblick auf Vererbung wie Klassen behandelt werden.

  21. Anmerkungen (Forts.) • Zugriffsspezifikationen • Element; • weiter; • NutzinfoDruck() als public Komponenten, da wir (nur an dieser Stelle !!) faul sind. Logisch wäre protected oder gar private besser. Vgl. Vorgehen in früheren Beispielen.

  22. Erste Formulierungen 2 (Wiederholung) • class Liste { • ListenEl * DieListe; • void ListenDruck(ListenEl *); • Liste() { • DieListe = NULL;}; • void Einfuegen(Nutzinfo *); • void Druck(){ListenDruck(DieListe);}

  23. Auch bei Parametern oder lokalen Variablen muß der Typparameter stets mitgeteilt werden. Formulierung als Klasse 3 • template <class Nutzinfo> • class Liste { • protected: • ListenEl<Nutzinfo> * DieListe; • void ListenDruck(ListenEl<Nutzinfo> *); • public: • Liste() { • DieListe = NULL;}; • void Einfuegen(Nutzinfo *); • void Druck(){ListenDruck(DieListe);} • };

  24. Realisierung der Methoden 1 • ListenEl<Nutzinfo> * • neu = new ListenEl<Nutzinfo>; template <class Nutzinfo> mußvor der Definition jeder Methode stehen Der Name des Typparameters muß bei der Angabe der Klasse genannt werden template <class Nutzinfo> void Liste<Nutzinfo>::Einfuegen(Nutzinfo * r){ neu->Element = r; neu->weiter = DieListe; DieListe = neu;} Auch hier: Typparameter

  25. Realisierung der Methoden 2 • template <class Nutzinfo> • void Liste<Nutzinfo>:: • ListenDruck(ListenEl<Nutzinfo> * K) { • if (K != NULL) { • K->NutzinfoDruck(); • ListenDruck(K->weiter); • } • }

  26. Realisierung der Methoden 3 • template <class Nutzinfo> • void Liste<Nutzinfo>::Einfuegen(Nutzinfo * r){ • ......} • Die Konstruktion müßte jetzt klar sein: • Angabe, daß es sich um eine Schablone mit Typparameter Nutzinfo handelt, • Nennung des Typparameters bei der Definition der Methode (hier: Einfuegen). Liste_einfach.cpp

  27. Anwendung: Liste komplexer Zahlen • class KomplexL: public Liste<KomplexeZahl> { • public: • KomplexL() : Liste<KomplexeZahl>() {};}; int main() { KomplexL * MeineKoZListe = new KomplexL(); for (int i = 0; i< 10;i++){ MeineKoZListe-> Einfuegen(new KomplexeZahl (rand()%100, rand()%100));}; MeineKoZListe->Druck();return 0;} Quelltext Komplexe Zahlen Programm

  28. Anwendung: Liste von Integer-Zahlen 1 • Erzeuge Klasse zu Integer-Zahlen: • class IntegerZahl { • public: • int i; • IntegerZahl (int i1) { i = i1;} • void Druck() { cout << i; } • int Get_i() {return i;} • bool Gleich(IntegerZahl *p) { • return (i == p->i);} • }; Hashing von Integern Liste von Integern

  29. Anwendung: Liste komplexer Zahlen Wdh • class KomplexL: public Liste<KomplexeZahl> { • public: • KomplexL() : Liste<KomplexeZahl>() {};}; int main() { KomplexL * MeineKoZListe = new KomplexL(); for (int i = 0; i< 10;i++){ MeineKoZListe-> Einfuegen(new KomplexeZahl (rand()%100, rand()%100));}; MeineKoZListe->Druck();return 0;}

  30. Anwendung: Liste von Integer-Zahlen 2 • class IntL: public Liste<IntegerZahl> { • public: • IntL() : Liste<IntegerZahl>() {};}; int main() { IntL * MeineIntListe = new IntL(); for (int i = 0; i< 10;i++){ MeineIntListe-> Einfuegen(new IntegerZahl (rand()%100));}; MeineIntListe->Druck();return 0;} Quelltext Integer Programm

  31. Anwendung: Liste von Beschäftigten • class BeschL: public Liste<Beschaeftigter> { • public: • BeschL() : Liste<Beschaeftigter>() {};}; int main() { BeschL * MeineBeschListe = new BeschL(); ..... MeineBeschListe-> Einfuegen(einBeschaeftigter); .......... MeineBeschListe->Druck();return 0;} Quelltext Klasse Beschäftigter Programm

  32. Anmerkungen • Die neue Klasse entsteht durch Konkretisie-rung des Typparameters. Das geschieht hier mittels Vererbung: class IntL: public Liste<IntegerZahl> { • ........ }; • Die (konkrete) Klasse Liste<IntegerZahl> entsteht dabei aus der Klasse(nschablone) Liste < Nutzinfo>, indem der Typparameter Nutzinfo durch IntegerZahl substituiert wird.

  33. Konsequenzen • Code für Listen wurde nur einmal formuliert • Für jeden Typ kann mit dieser Technik eine Liste formuliert werden. • Dazu muß lediglich formuliert werden: • ein Konstruktor, • // die virtuelle Methode ELDruck, die typspezifisch ist. • Dies geschieht hier durch Vererbung.

  34. Konsequenzen (Forts.) • Für jeden konkreten Typ, der den Typpara-meter ersetzt, wird bei der Ersetzung eine Klasse erzeugt (s.o.). • Diese kann im wesentlichen wie jede andere Klasse verwendet werden. • „Anonyme“ Klasse • Die Ersetzung des Typparameters kann auch dort geschehen, wo Klassen benutzt werden. --> vgl. Beispiel nächste Folien.

  35. Anwendung: Liste komplexer Zahlen UKlasse • class KomplexL: public Liste<KomplexeZahl> { • public: • KomplexL() : Liste<KomplexeZahl>() {};}; int main() { KomplexL * MeineKoZListe = new KomplexL(); for (int i = 0; i< 10;i++){ MeineKoZListe-> Einfuegen(new KomplexeZahl (rand()%100, rand()%100));}; MeineKoZListe->Druck();return 0;}

  36. Anwendung: Liste komplexer Zahlen anonym • /*class KomplexL: public Liste<KomplexeZahl> { • public: • KomplexL() : Liste<KomplexeZahl>() {};}; */ Programm int main() { Liste<KomplexeZahl> * MeineKoZListe = new Liste<KomplexeZahl>; for (int i = 0; i< 10;i++){ MeineKoZListe-> Einfuegen(new KomplexeZahl (rand()%100, rand()%100));}; MeineKoZListe->Druck();return 0;}

  37. Gliederung 1 • Neuer Anwendungsbereich • Klasse komplexe Zahlen • Einführung in Templates/Schablonen 1. Am Beispiel (einfache) Liste: • Schablone für (einfache) Liste. • Beispielanwendungen: • Einfache Liste für komplexe Zahlen • Einfache Liste für Integer • Einfache Liste für Beschäftigte • Konsequenzen • Detail: Erzeugung anonymer Klassen Erledigt !!

  38. Gliederung 2 2. Beispiel: Hashing allgemein • Annahmen • Liste(nschablone) • Schablone Hashtafel • Vergleich : int <---> Nutzinfo * • Methoden dazu • Beispielanwendungen: • Hashing für komplexe Zahlen • Hashing für Integer • Hashing für Wörter • Hashing für Beschäftigte nach Klassenzugehörigkeit • Hashing für Beschäftigte nach Verdienststufe

  39. Hashing für beliebige Datentypen • Hashing (Wiederholung): • Bisher formuliert für ganze Zahlen. • Zentral: Feld von Listen ganzer Zahlen, in die eingefügt wurde. • Feldelement wurde ermittelt durch Hashfunktion.

  40. Idee Hashfunktion (vgl. Kap. 18) • Formal: • Sei U die (endliche) Menge aller Objekte, für die die Suchoperationen definiert werden sollen. • h: U -> {0, ..., m-1} sei eine Funktion --> Hash-Fkt. • 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‘ ?

  41. 0 1 2 3 4 Bildchen Listen das Feld

  42. Hashing Verwendung • • Benutze die verketteten Listen, um: • Element t wird in der Liste zu h(t) abgespeichert. • Suche t? Schaue in der Liste zu h(t) nach. • Lösche t? Lösche t in der Liste zu h(t). • • Zentral: Hashfunktion h • Muß einfach zu berechnen sein • Sollte die Elemente (möglichst) gleichmäßig verteilen.

  43. Zur Schablone für Listen mit Typ Nutzinfo • Annahmen: • Für Objekte des Typs Nutzinfo ist eine Druck-Methode definiert. • Also: für qvom TypNutzinfo ist q.Druck() aufrufbar. • Objekte des Typs Nutzinfo können verglichen werden: • Fürp vom Typ Nutzinfo * und q vom Typ Nutzinfo* ist p->Gleich(q) definiert und gibt true oder false zurück.

  44. Listen- Schablone 1 • template <class Nutzinfo> • class ListenEl { • public: • Nutzinfo * Element; • ListenEl * weiter; • void NutzinfoDruck(){ • Element->Druck(); • cout<<endl; • } • };

  45. Listen- Schablone 2 • template <class Nutzinfo> • class Liste { • protected: • ListenEl<Nutzinfo> * DieListe; • bool IstDa(ListenEl<Nutzinfo>*, Nutzinfo*); • /* Testet, daß Nutzinfo in Liste */ • ListenEl<Nutzinfo> * WegDamit • (ListenEl<Nutzinfo> *, Nutzinfo *); • /* Entfernt Nutzinfo, falls in Liste • enthalten*/ • void ListenDruck(ListenEl<Nutzinfo> *);

  46. Listen- Schablone 3 • //class ListeFortsetzung • public: • Liste() {DieListe = NULL;}; • Liste(Nutzinfo * r) { • DieListe -> Element = r; • DieListe -> weiter = NULL;}; • bool Testen(Nutzinfo * r) { • return IstDa(DieListe, r);} • void Entfernen(Nutzinfo * r) { • DieListe = WegDamit(DieListe, r);} • void Einfuegen(Nutzinfo *);

  47. Listen- Schablone 4 • //class ListeFortsetzung 2 • void Druck(){ListenDruck(DieListe);} • int Gleich(Nutzinfo * p, Nutzinfo * q){ • return p->Gleich(q);} • /* In Nutzinfo muß also • Gleich(Nutzinfo *)definiert sein.*/ • int Laenge();

  48. Methode IstDa • template <class Nutzinfo> • bool Liste<Nutzinfo>::IstDa( • ListenEl<Nutzinfo> * K, Nutzinfo * r) { • if (K == NULL) • return false; • else { • if (Gleich(K->Element, r)) • return true; • else • return IstDa(K->weiter, r); • } • }

  49. Methode Einfuegen • template <class Nutzinfo> • void Liste<Nutzinfo>::Einfuegen(Nutzinfo * r) { • if(!Testen(r)) { • ListenEl<Nutzinfo> * neu • = new ListenEl<Nutzinfo>; • neu->Element = r; • neu->weiter = DieListe; • DieListe = neu; • }} • Zu Restlichen vgl. Implementierung im Quelltext Hash-List.cpp

More Related