Programmierung 1 Studiengang MI / WI Dipl.-Inf., Dipl.-Ing. (FH) Michael Wilhelm Hochschule Harz FB Automatisierung und Informatik [email protected] http://mwilhelm.hs-harz.de Raum 2.202 Tel. 03943 / 659 338 FB Automatisierung und Informatik: Programmierung 1, MI/WI 1 Inhalt der Vorlesung Überblick: • Erste Beispiele, Interaktion • elementare Datentypen • Variablen und Kontrollstrukturen • Arrays und Funktionen • Objekte und Methoden • Algorithmen und Pseudocode • Laufzeitverhalten • Simulation • Bibliotheken • Template und generische Klassen • • Grundlegende Algorithmen und Methoden: • Suchen und Sortieren • Hashing • Rekursion • Graphen • Dynamische Programmierung Von Processing zu Java Folien basierend auf Daniel Schiffman “Learning Processing” und Donald W. Smith Folien basierend auf Vorlesung „Programmierung1“ von Prof. Singer FB Automatisierung und Informatik: Programmierung 1, MI/WI 2 1 Kapitel Schnelles Suchen (Hashing) • • • Hash-Funktion Hash-Map Hash-Set FB Automatisierung und Informatik: Programmierung 1, MI/WI 3 Hashing / HashTable / HashMap / HashSet Definition Hashing: • Die Objekte werden in einem Feld mit Indizies 0 bis N-1 gespeichert. • Die einzelnen Speicherpositionen werden Buckets genannt. • Eine Hashfunktion h : e --> N bestimmt für ein Schlüsselelement e einen Bucket h(e) im Feld, in dem ein mit dem Schlüssel e assoziertes Element gespeichert werden soll. • Die Wahl der Funktion h hat entscheidenden Einfluss auf die Qualität des Verfahrens. Kollision: • Eine Kollision tritt auf, wenn für e1 ≠ e2 gilt h(e1) = h(e2) FB Automatisierung und Informatik: Programmierung 1, MI/WI 4 2 Beispiel: Wir wählen die ganzen Zahlen als Element e. Ein Feld der Größe N. Die Hashfunktion sei h(e) = e mod N. Gespeichert werden sollen 42 und 119. Hier ist N = 10. Index 0 Eintrag 1 2 3 4 5 6 7 8 42 9 119 Problem: • Es soll noch der Wert 69 gespeichert werden. Jedoch ist 69 mod 10 = 9. Dieser Bucket ist bereits belegt. Wie soll bei einer Kollision verfahren werden? Beachte: • Man kann zeigen: Idealerweise ist die Größe der Hashtabelle eine Primzahl, die aber nicht nahe bei einer Zweierpotenz liegen sollte. FB Automatisierung und Informatik: Programmierung 1, MI/WI 5 Hashfunktionen • Hashfunktionen sollen “gute” Eigenschaften besitzen. • Insbesondere sollen sie die zur Verfügung stehenden Buckets möglichst gleichmäßig füllen. • Sie sollen aber auch einfach berechenbar sein, denn die Kosten ein Element zu speichern sind direkt proportional zu den Kosten der Berechnung der Hashfunktion. • Der Zugriff auf Elemente einer Hashtabelle ist O(1). FB Automatisierung und Informatik: Programmierung 1, MI/WI 6 3 Hashfunktionen Umgang mit Kollisionen: • Verkettung: • Alle kollidierenden Elemente werden im selben Bucket gespeichert, etwa in einer ArrayList. • Sondieren: suche einen freien Bucket • lineares Sondieren • quadratisches Sondieren FB Automatisierung und Informatik: Programmierung 1, MI/WI 7 Doppelte Hashwerte in einer Liste speichern • • Ein Überläufer ist ein Element, welches eine bereits gefüllte Position in der Hashtabelle zum Überlaufen bringt. Bei der Verkettung der Überläufer werden diese für jeden Bucket in einem Array [oder einer verketteten Liste (siehe 2. Semester)] untergebracht. Bei vielen Überläufern kann die Tabelle entarten, d.h. viele Elemente befinden sich in einem gemeinsamen Bucket, mit Zugriffszeiten von O(N). Index 0 1 2 3 4 5 6 7 8 9 Eintrag 109 42 FB Automatisierung und Informatik: Programmierung 1, MI/WI 69 8 4 Lineares Sondieren • • • Bei einer Kollision für T[h(e]] werden der Reihe nach die Buckets überprüft • T[h(e) + 1]; T[h(e) + 2], ..... Das Element wird im ersten so gefundenen freien Bucket abgespeichert. Hierbei bezeichnet T[x] den zu x mod N gehörigen Bucket. Index 0 1 Eintrag 69 29 2 3 4 5 6 7 8 42 9 119 FB Automatisierung und Informatik: Programmierung 1, MI/WI 9 Quadratisches Sondieren • • lineares Sondieren führt oft zu einer Konzentration der Elemente in der Nähe weniger Buckets. Quadratisches Sondieren verhindert dies. • T[h(e) + 1]; T[h(e) + 4]; T[h(e) + 9]; .... Index 0 Eintrag 69 1 2 3 42 29 4 5 6 FB Automatisierung und Informatik: Programmierung 1, MI/WI 7 8 9 119 10 5 Re-Hashing • Wird keine Verkettung der Überläufer durchgeführt, so muss die Hashtabelle groß genug sein um alle zu speichernden Elemente aufnehmen zu können. • Sollte dies nicht der Fall sein, muss sie entsprechend vergrößert werden. • Dann muss für jeden Eintrag ein neuer Bucket, entsprechend der neu berechneten Hashfunktion, bestimmt werden. FB Automatisierung und Informatik: Programmierung 1, MI/WI 11 Hashfunktion und equals • • • Beachte: Falls die Hashfunktion für zwei Objekte denselben Wert ergibt, folgt hieraus nicht, dass die beiden Objekte gleich sind. Aber da zwei gleiche Objekte denselben Hashwert haben müssen, heißt dies auch: • Falls der Hashwert zweier Objekte nicht gleich ist, können auch die Objekte nicht gleich sein. In mathematischer Notation für die Objekte A und B sowie ihre Hashwerte hA und hB: A = B ⇒ hA = hB hA = hB ⇔ hA ≠ hB ⇒ A ≠ B ⇏ A=B FB Automatisierung und Informatik: Programmierung 1, MI/WI 12 6 hashcode und equals • • • Menü Source Falls Objekte in Hashtabellen (oder allgemeiner in Collections) gespeichert werden sollen, muss immer eine entsprechende equals-Methode implementiert sein. Diese muss immer konsistent mit der hashCode-Methode sein. Also, falls Sie equals implementieren, dann sollten Sie auch hashCode implementieren und umgekehrt Eclipse kann equals und hashCode für eine Klasse automatisch erzeugen. FB Automatisierung und Informatik: Programmierung 1, MI/WI 13 FB Automatisierung und Informatik: Programmierung 1, MI/WI 14 7 @Override public int hashCode() { final int prime = 31; int result = 1; if (firma == null) result=prime*result+ firma.hashCode(); else result = 0; result = prime * result + kw; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Auto other = (Auto) obj; if (firma == null) { if (other.firma != null) return false; } else if (!firma.equals(other.firma)) return false; if (kw != other.kw) return false; return true; } FB Automatisierung und Informatik: Programmierung 1, MI/WI 15 HashMap in Java • HashMap in Java: Schlüssel (hier String) und Wert (hier Klasse) getrennt. HashMap<String, Klasse> hash; hash = new HashMap<String, Klasse>(); hash.put("variable", new Klasse()); Klasse k = hash.get("variable"); • • • typische Anwendung: • Datenbanken mögliche Schlüssel: • Name, Steuernummer, ... Wert: alle weiteren Daten: • Adresse, Familienstand, Handypro!le, ... FB Automatisierung und Informatik: Programmierung 1, MI/WI 16 8 HashSet in Java (verwaltet eine Menge) • HashSet in Java: Schlüssel (via hashCode) und Wert gemeinsam in Klasse. HashSet<Klasse> hash = new HashSet<Klasse>(); Klasse k = new Klasse(); hash.add(k); boolean found = hash.contains(k); • • HashSet hat Eigenschaften einer Menge, d.h. kein Element kann mehrfach auftreten (equals). Dies muss gegebenenfalls vor dem Einfügen überprüft werden. FB Automatisierung und Informatik: Programmierung 1, MI/WI 17 Zusammenfassung • • • • Interfaces erlauben Verträge über zu implementierende Methoden in Klassen abzuschliessen. Generische Klassen dienen der typsicheren Programmierung. Der Compiler entfernt beim Übersetzen diese Information. ArrayList<T> implementiert dynamisch wachsende Arrays. Hashing berechnet den Index in einem Array an dem Information abgelegt werden soll. • Hash-Indizes sind nicht eindeutig -- es können Kollisionen auftreten. • Kollision werden mit Verkettung oder (linearem, quadratischem) Sondieren behandelt. • Java hat Hashing als HashMap<Key, Value> und als HashSet<Key> implementiert. FB Automatisierung und Informatik: Programmierung 1, MI/WI 18 9