<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Hashtabelle</id>
	<title>Hashtabelle - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Hashtabelle"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Hashtabelle&amp;action=history"/>
	<updated>2026-05-26T10:50:05Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Hashtabelle&amp;diff=112961&amp;oldid=prev</id>
		<title>imported&gt;SchlurcherBot: Bot: http → https</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Hashtabelle&amp;diff=112961&amp;oldid=prev"/>
		<updated>2026-01-08T00:53:42Z</updated>

		<summary type="html">&lt;p&gt;Bot: http → https&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;In der [[Informatik]] bezeichnet man eine spezielle [[Indexstruktur]] als &amp;#039;&amp;#039;&amp;#039;Hashtabelle&amp;#039;&amp;#039;&amp;#039; ({{enS|&amp;#039;&amp;#039;hash table&amp;#039;&amp;#039;}} oder {{lang|en|&amp;#039;&amp;#039;hash map&amp;#039;&amp;#039;}}) bzw. &amp;#039;&amp;#039;&amp;#039;[[Streuwert]]&amp;lt;nowiki/&amp;gt;tabelle&amp;#039;&amp;#039;&amp;#039;. Sie wird verwendet, um [[Datenelement]]e in einer großen Datenmenge zu suchen bzw. aufzufinden (&amp;#039;&amp;#039;Hash-&amp;#039;&amp;#039; oder &amp;#039;&amp;#039;Streuspeicherverfahren&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
Gegenüber alternativen Index-Datenstrukturen wie [[Baum (Graphentheorie)|Baumstrukturen]] (z.&amp;amp;nbsp;B. ein [[B+-Baum]]) oder [[Liste (Datenstruktur) #Skip-Liste|Skip-Listen]] zeichnen sich Hashtabellen üblicherweise durch einen konstanten Zeitaufwand bei Einfüge- bzw. Entfernen-Operationen aus.&lt;br /&gt;
&lt;br /&gt;
== Hashverfahren ==&lt;br /&gt;
Das Hashverfahren ist ein Algorithmus zum Suchen von Datenobjekten in großen Datenmengen. Es basiert auf der Idee, dass eine [[mathematische Funktion]], die [[Hashfunktion]], die Position eines Objektes in einer Tabelle berechnet. Dadurch erübrigt sich das Durchsuchen vieler Datenobjekte, bis das Zielobjekt gefunden wurde.&lt;br /&gt;
&lt;br /&gt;
== Der Algorithmus ==&lt;br /&gt;
Beim Hashverfahren werden die Zieldaten in einer Hashtabelle gespeichert. Dabei dient &amp;#039;&amp;#039;nicht&amp;#039;&amp;#039; der [[Schlüssel (Datenbank)|Schlüssel]], der das Datenobjekt eindeutig identifiziert, als [[Indexstruktur|Index]], sondern der Hashwert, der von einer Hashfunktion aus dem Schlüssel berechnet wird. Der durch den Hashwert festgelegte Speicherort eines Datenobjektes in der Tabelle wird auch als &amp;#039;&amp;#039;Bucket&amp;#039;&amp;#039; bezeichnet ({{enS|Behälter}}).&lt;br /&gt;
&lt;br /&gt;
Im Idealfall bekommt jedes Objekt einen eigenen Bucket (d.&amp;amp;nbsp;h. keine Kollisionen, s.&amp;amp;nbsp;u.).&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird die Tabelle als ein [[Feld (Datentyp)|Array]] implementiert.&lt;br /&gt;
&lt;br /&gt;
=== Kollisionen ===&lt;br /&gt;
Hashfunktionen sind im Allgemeinen &amp;#039;&amp;#039;nicht&amp;#039;&amp;#039; [[Injektivität|injektiv]], d.&amp;amp;nbsp;h. zwei unterschiedliche Schlüssel können zum selben Hashwert, also zum selben Feld in der Tabelle, führen. Dieses Ereignis wird als &amp;#039;&amp;#039;Kollision&amp;#039;&amp;#039; bezeichnet. In diesem Fall muss die Hashtabelle mehrere Werte an derselben Stelle / in demselben Bucket aufnehmen.&lt;br /&gt;
&lt;br /&gt;
Eine Kollision benötigt bei der Suche eine spezielle Behandlung durch das Verfahren: Zunächst wird aus einem Suchschlüssel wieder ein Hashwert berechnet, der den Bucket des gesuchten Datenobjektes bestimmt; dann muss noch durch direkten Vergleich des Suchschlüssels mit den Objekten im Bucket das gesuchte Ziel bestimmt werden.&lt;br /&gt;
&lt;br /&gt;
Zur Behandlung von Kollisionen werden kollidierte Daten nach einer Ausweichstrategie in alternativen Feldern oder in einer Liste gespeichert. Schlimmstenfalls können Kollisionen zu einer [[Entartung (Informatik)|Entartung]] der Hashtabelle führen, wenn wenige Hashwerte sehr vielen Objekten zugewiesen wurden, während andere Hashwerte unbenutzt bleiben.&lt;br /&gt;
&lt;br /&gt;
==== Kollisionsauflösungsstrategien ====&lt;br /&gt;
Um das Kollisions-Problem zu handhaben, gibt es diverse Kollisionsauflösungsstrategien.&lt;br /&gt;
&lt;br /&gt;
===== Geschlossenes Hashing mit offener Adressierung =====&lt;br /&gt;
Eine Möglichkeit wird &amp;#039;&amp;#039;geschlossenes Hashing mit offener Adressierung&amp;#039;&amp;#039; genannt. Wenn dabei ein Eintrag an einer schon belegten Stelle in der Tabelle abgelegt werden soll, wird stattdessen eine andere freie Stelle genommen. Häufig werden drei Varianten unterschieden (vgl. [[#Algorithmen]]):&lt;br /&gt;
&lt;br /&gt;
; lineares Sondieren&lt;br /&gt;
: es wird um ein konstantes Intervall verschoben nach einer freien Stelle gesucht. Meistens wird die Intervallgröße auf&amp;amp;nbsp;1 festgelegt.&lt;br /&gt;
; quadratisches Sondieren&lt;br /&gt;
: Nach jedem erfolglosen Suchschritt wird das Intervall quadriert.&lt;br /&gt;
; doppeltes Hashen&lt;br /&gt;
: eine weitere Hash-Funktion liefert das Intervall.&lt;br /&gt;
&lt;br /&gt;
===== Offenes Hashing mit geschlossener Adressierung =====&lt;br /&gt;
Eine weitere Möglichkeit ist &amp;#039;&amp;#039;offenes Hashing mit geschlossener Adressierung&amp;#039;&amp;#039;. Anstelle der gesuchten Daten enthält die Hashtabelle hier Behälter ({{enS|&amp;#039;&amp;#039;Buckets&amp;#039;&amp;#039;}}), die alle Daten mit gleichem Hash-Wert aufnehmen. Bei einer Suche wird also zunächst der richtige Zielbehälter berechnet. Damit wird die Menge der möglichen Ziele erheblich eingeschränkt.&lt;br /&gt;
&lt;br /&gt;
Dennoch müssen abschließend die verbliebenen Elemente im Behälter durchsucht werden. Im schlimmsten Fall kann es passieren, dass alle Elemente gleiche Hash-Werte haben und damit im selben Bucket abgelegt werden. In der Praxis kann das aber durch die Wahl einer geeigneten Größe für die Hashtabelle sowie einer geeigneten Hash-Funktion vermieden werden.&lt;br /&gt;
&lt;br /&gt;
Oft wird die [[Relation (Mathematik)#Verkettung von Relationen|Verkettung]] durch eine [[Liste (Datenstruktur)|lineare Liste]] pro Behälter realisiert.&lt;br /&gt;
&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
Je nach Anwendungsfall hat eine Hashtabelle Vorteile sowohl in der [[Zugriffszeit]] (gegenüber anderen Baumindexstrukturen) als auch im benötigten [[Speicherplatz]] (gegenüber gewöhnlichen Arrays).&lt;br /&gt;
&lt;br /&gt;
Idealerweise sollte die Hashfunktion für die zu speichernden Daten so gewählt sein, dass die Anzahl der Kollisionen minimiert wird und unter einer Konstante bleibt; je nach Hashfunktion muss die Hashtabelle dafür ungenutzte Felder enthalten (in der Praxis üblicherweise 20 bis 30&amp;amp;nbsp;Prozent). Trifft dies zu, dann benötigt eine Hashtabelle mit &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; gespeicherten Elementen per [[Speicherzugriff|Zugriff]] ({{enS|&amp;#039;&amp;#039;Look-Up&amp;#039;&amp;#039;}}) auf einen Hashtabellen-Eintrag im Mittel nur konstanten Zeitaufwand ([[Landau-Symbole|O(1)]]).&lt;br /&gt;
&lt;br /&gt;
Im Vergleich dazu ist der Zugriff auf ein Element in einem B-Baum in der Größenordnung von &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;, wobei das&amp;amp;nbsp;&amp;#039;&amp;#039;n&amp;#039;&amp;#039; der Anzahl der in der Hashtabelle gespeicherten Einträge entspricht. Die komplette Baum-Datenstruktur benötigt Speicher in der Größenordnung von &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
Wegen der möglichen Kollisionen hat eine Hashtabelle im [[Worst-Case]] ein sehr schlechtes Zugriffszeit-Verhalten. Dieser wird mit &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; abgeschätzt; es werden dabei also alle Einträge in der Tabelle durchsucht.&lt;br /&gt;
&lt;br /&gt;
Als Füllgrad wird die Anzahl der gespeicherten Elemente geteilt durch die Anzahl aller Buckets bezeichnet:&lt;br /&gt;
&lt;br /&gt;
:Füllgrad = gespeicherte Elemente/Buckets.&lt;br /&gt;
&lt;br /&gt;
Mit steigendem Füllgrad wächst die Wahrscheinlichkeit einer Kollision, und die Entartung nimmt zu. Dann kann nur eine Vergrößerung der Tabelle mit nachfolgender Restrukturierung wieder zu akzeptablem Laufzeitverhalten führen.&lt;br /&gt;
&lt;br /&gt;
Außerdem bringt eine der Suchoperation nachfolgende Nachbarschaftssuche nichts, da eine [[Ordnungsrelation|Ordnungsbeziehung]] zwischen den Schlüsseln erklärtermaßen nicht gepflegt wird (s.&amp;amp;nbsp;a. Abschnitt [[#Datenbanken|Datenbanken]]).&lt;br /&gt;
&lt;br /&gt;
== Varianten ==&lt;br /&gt;
Es gibt mehrere Varianten des Hashverfahrens, die sich für bestimmte Daten besser eignen. Ein wichtiger Faktor hierbei ist die Dynamik, mit der sich die Anzahl der Elemente ändert. Das offene Hashing löst dieses Problem, nimmt aber Einbußen bei den Zugriffszeiten in Kauf. Das geschlossene Hashing ist hingegen auf explizite Strategien zur Kollisionsbehandlung angewiesen. &amp;lt;br&amp;gt;Vorsicht: Die Bezeichnungen offenes bzw. geschlossenes Hashing werden auch in genau umgekehrter Bedeutung verwendet.&lt;br /&gt;
&lt;br /&gt;
=== Hashing mit Verkettung ===&lt;br /&gt;
[[Datei:Hash table 5 0 1 1 1 1 1 LL.svg|mini|450x450px|Kollision, die mit &amp;#039;&amp;#039;separate chaining&amp;#039;&amp;#039; aufgelöst wird.]]&lt;br /&gt;
Beim Hashing mit Verkettung ({{enS|&amp;#039;&amp;#039;separate chaining&amp;#039;&amp;#039;}}) ist die Hash-Tabelle so strukturiert, dass jeder Behälter eine dynamische Datenstruktur aufnehmen kann – beispielsweise eine [[Liste (Datenstruktur)|Liste]] oder einen [[Baum (Graphentheorie)|Baum]]. Jeder Schlüssel wird dann in dieser Datenstruktur eingetragen oder gesucht. So ist es problemlos möglich, mehrere Schlüssel in einem Behälter abzulegen, was allerdings zu mehr oder weniger verlängerten Zugriffszeiten führt. Die Effizienz des Zugriffs wird dabei davon bestimmt, wie schnell Datensätze in die gewählte Datenstruktur eingefügt und darin wiedergefunden werden können. Hashing mit Verkettung ist bei Datenbanken eine sehr gängige Indizierungsvariante, wobei sehr große Datenmengen mittels Hashtabellen indiziert werden. Die Größe der Buckets ist in Datenbanksystemen ein Vielfaches der [[Datenblock|Sektor]]engröße des Speichermediums. Der Grund dafür ist, dass die Datenmenge nicht mehr im Hauptspeicher gehalten werden kann. Bei einer Suchanfrage muss das Datenbanksystem die Buckets sektorenweise einlesen.&lt;br /&gt;
&lt;br /&gt;
Jeder Behälter ist unabhängig und weist eine Art Liste von Einträgen mit demselben Index auf. Die Zeit für [[Operation (Informatik)|Operationen]] der Hashtabelle ist die Zeit zum Suchen des Behälters, die konstant ist, plus die Zeit für die Listenoperation. In einer guten Hashtabelle hat jeder Behälter keinen oder einen Eintrag und manchmal zwei oder drei, aber selten mehr. Daher werden für diese Fälle zeit- und raumeffiziente Strukturen bevorzugt. Strukturen, die für eine ziemlich große Anzahl von Einträgen pro Behälter effizient sind, sind nicht erforderlich oder wünschenswert. Wenn diese Fälle häufig auftreten, funktioniert das [[Hashing]] nicht gut, und dies muss behoben werden.&lt;br /&gt;
&lt;br /&gt;
=== Hashing mit offener Adressierung ===&lt;br /&gt;
[[Datei:Hash table 5 0 1 1 1 1 0 SP.svg|mini|380x380px|Kollision, die mit &amp;#039;&amp;#039;open addressing&amp;#039;&amp;#039; aufgelöst wird. „Ted Baker“ hat einen eindeutigen Hashwert, kollidiert aber mit „Sandra Dee“, die vorher mit „John Smith“ kollidiert ist.]]&lt;br /&gt;
Dieses Verfahren wird abgekürzt auch &amp;#039;&amp;#039;offenes Hashing&amp;#039;&amp;#039; oder &amp;#039;&amp;#039;geschlossenes Hashing&amp;#039;&amp;#039; genannt. Der Name &amp;#039;&amp;#039;offenes Hashing&amp;#039;&amp;#039; bezieht sich auf die offene Adressierung, während der Name &amp;#039;&amp;#039;geschlossenes Hashing&amp;#039;&amp;#039; sich auf die begrenzte Anzahl möglicher Schlüssel im Behälter bezieht.&lt;br /&gt;
&lt;br /&gt;
Beim Hashing mit offener Adressierung kann jedem Behälter nur eine feste Anzahl von Schlüsseln zugewiesen werden. Häufig wählt man einfach einen einzigen möglichen Schlüssel pro Behälter. Im Kollisionsfall muss dann nach einem alternativen Behälter gesucht werden. Dabei geht man so vor, dass man für &amp;#039;&amp;#039;m&amp;#039;&amp;#039; Behälter eine ganze Folge von &amp;#039;&amp;#039;m&amp;#039;&amp;#039; Hash-Funktionen definiert. Führt die Anwendung der ersten Hash-Funktion, nennen wir sie &amp;#039;&amp;#039;h&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039;, zu einer Kollision, so wendet man &amp;#039;&amp;#039;h&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039; an. Führt diese ebenfalls zu einer Kollision (d.&amp;amp;nbsp;h. der entsprechende Behälter ist bereits belegt), so wendet man &amp;#039;&amp;#039;h&amp;lt;sub&amp;gt;3&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039; an, und so weiter, bis &amp;#039;&amp;#039;h&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;&amp;#039;&amp;#039; bzw. bis ein leerer Behälter gefunden wird. Die Bezeichnung „offene Adressierung“ ergibt sich aus der Eigenschaft, dass durch Kollisionen gleiche Schlüssel unterschiedliche Adressen zugewiesen bekommen können.&lt;br /&gt;
&lt;br /&gt;
Alle Eintragsdatensätze werden im Behälter selbst gespeichert. Wenn ein neuer Eintrag eingefügt werden muss, werden die Behälter untersucht, beginnend mit dem Hash-zu-Slot und fortschreitend in einer bestimmten Prüfsequenz, bis ein unbesetzter Behälter gefunden wird. Bei der Suche nach einem Eintrag werden die Behälter in der gleichen Reihenfolge durchsucht, bis entweder der Zieldatensatz oder ein ungenutzter Behälter gefunden wird, was anzeigt, dass es keinen solchen Schlüssel in der Tabelle gibt. Der Name &amp;#039;&amp;#039;offenes Hashing&amp;#039;&amp;#039; bezieht sich darauf, dass der Ort des Elements nicht durch seinen Hashwert bestimmt wird.&lt;br /&gt;
&lt;br /&gt;
=== Kuckucks-Hashing ===&lt;br /&gt;
[[Kuckucks-Hashing]] ist ein weiteres Verfahren, Kollisionen in einer Tabelle zu vermeiden. Der Name leitet sich vom Verhalten des Kuckucks ab, Eier aus einem Nest zu entfernen, um ein eigenes Ei hineinzulegen.&lt;br /&gt;
&lt;br /&gt;
Das Prinzip ist, zwei Hash-Funktionen einzusetzen. Das ergibt zwei mögliche Speicherorte in einer Hashtabelle, was sehr viel häufiger eine konstante Zugriffszeit garantiert. Ein neuer Schlüssel wird an einem der zwei möglichen Orte gespeichert. Sollte die erste Zielposition besetzt sein, wird der bereits vorhandene Schlüssel auf seine alternative Position versetzt und an seiner Stelle der neue Schlüssel gespeichert. Sollte die alternative Position besetzt sein, so wird wiederum der Schlüssel auf dieser Position auf seine alternative Position transferiert, und so fort. Wenn diese Prozedur zu einer unendlichen Schleife führt (üblicherweise bricht man nach &amp;lt;math&amp;gt;\log n&amp;lt;/math&amp;gt; Schritten ab), wird die Hashtabelle mit zwei neuen Hash-Funktionen neu aufgebaut. Die Wahrscheinlichkeit für ein solches Rehashing liegt in der Größenordnung von &amp;lt;math&amp;gt;O(1/n)&amp;lt;/math&amp;gt; für jedes Einfügen.&lt;br /&gt;
&lt;br /&gt;
=== Algorithmen ===&lt;br /&gt;
==== Lineares Sondieren ====&lt;br /&gt;
Die einfachste Möglichkeit zur Definition einer solchen Folge besteht darin, so lange den jeweils nächsten Behälter zu prüfen, bis man auf einen leeren Behälter trifft. Die Definition der Folge von [[Hashfunktion]]en sieht dann so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;h_i(x) = (h(x) + i) \; \bmod~m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung des [[Operator (Mathematik)|Operators]] [[Modulo]] hat mit der begrenzten Zahl von Behältern zu tun: Wurde der letzte Behälter geprüft, so beginnt man wieder beim ersten Behälter. Das Problem dieser Methode ist, dass sich so schnell Ketten oder Cluster bilden und die Zugriffszeiten im Bereich solcher Ketten schnell ansteigen. Das lineare Sondieren ist daher wenig effizient. Sein Vorteil ist jedoch, dass – im Gegensatz zu anderen Sondierungsverfahren – alle Behälter der Tabelle benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Um ein Element &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; zu finden, berechnet man &amp;lt;math&amp;gt;h(x)&amp;lt;/math&amp;gt; und beginnt dort mit der Suche. Man durchläuft das [[Array (Datentyp)|Array]], bis entweder das Element gefunden oder ein leerer Behälter erkannt wird. Löschungen sind etwas schwieriger als beim Hashing mit Verkettung, denn man kann nicht einfach eine Suche durchführen und das Element dort löschen, wo man es findet. Löschungen werden häufig mithilfe von sogenannten &amp;#039;&amp;#039;Tombstones&amp;#039;&amp;#039; umgesetzt. Beim Löschen eines Elements wird markiert, dass der Behälter leer ist und zuvor belegt war. Beim Suchen bleibt man nicht bei einem &amp;#039;&amp;#039;Tombstone&amp;#039;&amp;#039; stehen. Stattdessen setzt man die Suche fort. Man muss dabei auf das Ende des Arrays achten und gegebenenfalls wieder am Anfang beginnen. Beim Einfügen kann jeder &amp;#039;&amp;#039;Tombstone&amp;#039;&amp;#039;, auf den man stößt durch einen leeren Behälter ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
In der Praxis ist lineares Sondieren eine der schnellsten Hashing-Algorithmen. Vorteilhaft ist der geringe Speicheraufwand. Man benötigt lediglich ein Array und eine sehr einfache [[Hashfunktion]]. Hervorragende Lokalität: Bei Kollisionen suchen wir nur an benachbarten Orten im Array. Bei der linearen Abtastung kommt es zu erheblichen Leistungseinbußen, wenn der Lastfaktor hoch wird. Die Anzahl der Kollisionen nimmt tendenziell mit der Anzahl der bestehenden Kollisionen zu. Dies wird als primäres Clustering bezeichnet.&amp;lt;ref&amp;gt;Stanford University: [https://web.stanford.edu/class/archive/cs/cs166/cs166.1166/lectures/12/Small12.pdf Linear Probing]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; Elemente in eine [[Array (Datentyp)|Array]] mit &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; Behältern eingefügt werden, ist der Lastfaktor &amp;lt;math&amp;gt;\alpha = \tfrac{n}{m}&amp;lt;/math&amp;gt;. Der [[Erwartungswert]] für die Anzahl der Schlüssel pro Behälter bei einer nicht erfolgreichen Suche beträgt dann &amp;lt;math&amp;gt;\tfrac{1}{2} \cdot \left(1 + \left(\tfrac{1}{1 - \alpha}\right)^2\right)&amp;lt;/math&amp;gt;. Der Erwartungswert bei einer erfolgreichen Suche eines zufälligen Elements beträgt &amp;lt;math&amp;gt;\tfrac{1}{2} \cdot \left(1 + \tfrac{1}{1 - \alpha}\right)&amp;lt;/math&amp;gt;.&amp;lt;ref&amp;gt;Uri Zwick, Tel Aviv University: [https://www.cs.tau.ac.il/~zwick/Adv-Alg-2015/Linear-Probing.pdf Hash Tables: Linear Probing]&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;:0&amp;quot;&amp;gt;O. Bittel, Hochschule Konstanz: [https://www-home.htwg-konstanz.de/~bittel/ain_alda/Vorlesung/02_Suchen_Hashverfahren.pdf Algorithmen und Datenstrukturen – Hashverfahren]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Quadratisches Sondieren ====&lt;br /&gt;
Wie beim linearen Sondieren wird nach einem neuen freien Speicher gesucht, allerdings nicht sequenziell, sondern mit stetig quadratisch wachsendem Abstand zur ursprünglichen Position und in beide Richtungen. Verursacht &amp;lt;math&amp;gt;h(k)&amp;lt;/math&amp;gt; eine Kollision, so werden nacheinander &amp;lt;math&amp;gt;h(k) + 1 , h(k) - 1 , h(k) + 4 , h(k) - 4 , h(k) + 9&amp;lt;/math&amp;gt; usw. probiert. In Formeln ausgedrückt:&lt;br /&gt;
&amp;lt;math&amp;gt;h_i(x) = \left(h(x) + (-1)^{i+1} \cdot \left\lceil\frac{i}{2}\right\rceil^2\right) \bmod~m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Den ständigen Wechsel des [[Vorzeichen (Zahl)|Vorzeichens]] bei dieser Kollisionsstrategie nennt man auch „alternierendes quadratisches Sondieren“ oder „quadratisches Sondieren mit Verfeinerung“. Wählt man die Anzahl der Behälter geschickt (nämlich &amp;lt;math&amp;gt;m = 4 \cdot j + 3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; ist [[Primzahl]]), so erzeugt jede Sondierungsfolge &amp;lt;math&amp;gt;h_0(x)&amp;lt;/math&amp;gt; bis &amp;lt;math&amp;gt;h_{m-1}(x)&amp;lt;/math&amp;gt; eine [[Permutation]] der Zahlen 0 bis &amp;lt;math&amp;gt;m-1&amp;lt;/math&amp;gt;; so wird also sichergestellt, dass jeder Behälter getroffen wird.&amp;lt;ref&amp;gt;Martin Lercher, Heinrich-Heine-Universität Düsseldorf: [https://www.cs.hhu.de/fileadmin/redaktion/Fakultaeten/Mathematisch-Naturwissenschaftliche_Fakultaet/Informatik/Computational_Cell_Biology/AlDat/Alg2016_05.pdf Algorithmen und Datenstrukturen - Hash-Verfahren]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Quadratisches Sondieren ergibt keine Verbesserung für die Wahrscheinlichkeit eine Sondierung durchführen zu müssen (&amp;lt;math&amp;gt;h_0(x) = h_0(y)&amp;lt;/math&amp;gt;), kann aber die Wahrscheinlichkeit von Kollisionen während der Sondierung (&amp;lt;math&amp;gt;h_0(x) = h_k(y)&amp;lt;/math&amp;gt;) herabsetzen, d.&amp;amp;nbsp;h. Clusterbildung wird vermieden.&lt;br /&gt;
&lt;br /&gt;
Das quadratische Sondieren verhindert die Cluster, die beim linearen Sondieren entstehen, ist aber nicht optimal. Beim quadratische Sondieren entsteht sogenanntes &amp;#039;&amp;#039;sekundäres Clustering&amp;#039;&amp;#039;. Dies geschieht, denn wenn zwei Schlüssel nahe beieinander liegende [[Hashwert]]e haben, liegen die entsprechenden sondierten Behälter ebenfalls nahe beieinander. Zusätzlich gibt es einen anderen Nachteil. Im Gegensatz zum linearen Sondieren, das garantiert jeden Behälter ausprobiert, stehen für das quadratische Sondieren in einigen Fällen nur &amp;lt;math&amp;gt;\lfloor \tfrac{m}{2} \rfloor&amp;lt;/math&amp;gt; Behälter zur Auswahl.&amp;lt;ref&amp;gt;Dave Mount, University of Maryland: [https://www.cs.umd.edu/class/fall2020/cmsc420-0201/Lects/lect14-hashing.pdf Hashing]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der [[Erwartungswert]] für die Anzahl der Schlüssel pro Behälter bei einer nicht erfolgreichen Suche beträgt &amp;lt;math&amp;gt;\tfrac{1}{1 - \alpha} - \alpha + \ln\left(\tfrac{1}{1 - \alpha}\right)&amp;lt;/math&amp;gt;. Der Erwartungswert bei einer erfolgreichen Suche eines zufälligen Elements beträgt &amp;lt;math&amp;gt;1 + \ln\left(\tfrac{1}{1 - \alpha}\right) - \tfrac{\alpha}{2}&amp;lt;/math&amp;gt;.&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Doppel-Hashing ====&lt;br /&gt;
Beim [[Doppel-Hashing]] werden zwei unabhängige Hash-Funktionen &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;h&amp;#039;&amp;lt;/math&amp;gt; angewandt. Diese heißen unabhängig, wenn die Wahrscheinlichkeit für eine sogenannte Doppelkollision, d.&amp;amp;nbsp;h. &amp;lt;math&amp;gt;h(x)=h(y) \land h&amp;#039;(x)=h&amp;#039;(y)&amp;lt;/math&amp;gt; gleich &amp;lt;math&amp;gt;1/m^2&amp;lt;/math&amp;gt; und damit minimal ist. Die Folge von Hash-Funktionen, die nun mittels &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;h&amp;#039;&amp;lt;/math&amp;gt; gebildet werden, sieht so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;h_i(x) = (h(x)+h&amp;#039;(x)\cdot i) ~ \bmod ~ m&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Kosten für diese Methode sind nahe den Kosten für ein ideales Hashing.&lt;br /&gt;
&lt;br /&gt;
Eine interessante Variante des Doppel-Hashing ist das Robin-Hood-Hashing. Die Idee ist, dass ein neuer Schlüssel einen bereits eingefügten Schlüssel verdrängen kann, wenn seine Prüfwert größer ist als die des Schlüssels an der aktuellen Position. Der Nettoeffekt davon ist, dass es die Worst Case Suchzeiten in der Tabelle reduziert. Weil sowohl der Worst Case als auch die Variation der Anzahl der Sonden drastisch reduziert werden, besteht eine interessante Variation darin, die Tabelle beginnend mit der erwarteten erfolgreichen Prüfwert zu durchsuchen und dann von dieser Position aus in beide Richtungen zu erweitern.&lt;br /&gt;
&lt;br /&gt;
Der [[Erwartungswert]] für die Anzahl der Schlüssel pro Behälter bei einer nicht erfolgreichen Suche beträgt &amp;lt;math&amp;gt;\tfrac{1}{1 - \alpha}&amp;lt;/math&amp;gt;. Der Erwartungswert bei einer erfolgreichen Suche eines zufälligen Elements beträgt &amp;lt;math&amp;gt;\tfrac{1}{\alpha} \cdot \ln\left(\tfrac{1}{1 - \alpha}\right)&amp;lt;/math&amp;gt;.&amp;lt;ref name=&amp;quot;:0&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Brent-Bansley-Hashing ====&lt;br /&gt;
Beim [[Brent-Hashing|Brent-Bansley-Hashing]] wird geprüft, ob der Platz, an dem das Element eingefügt werden soll, frei ist. Ist das der Fall, dann wird das Element dort eingefügt. Ist der Platz jedoch belegt, dann wird anhand des gerade berechneten Platzes jeweils für das einzufügende Element und für das Element, das schon an dem Platz ist, ein neuer Platz in der Tabelle berechnet. Sind die beiden neu berechneten Plätze auch belegt, wiederholt sich die Prozedur für den neu berechneten belegten Platz des einzufügenden Elementes. Wird jedoch für das einzufügende Element ein Platz berechnet, der frei ist, wird das Element dort eingefügt. Ist der Platz jedoch belegt und der berechnete Platz frei für das Element, das im vorherigen Durchlauf den Platz für das einzufügende Element belegt hat, dann werden die beiden Plätze der Elemente vertauscht und damit konnte das einzufügende Element in der Tabelle untergebracht werden.&lt;br /&gt;
&lt;br /&gt;
=== Dynamisches Hashing ===&lt;br /&gt;
Bei steigendem Füllgrad der Tabelle steigt die Wahrscheinlichkeit von Kollisionen deutlich an. Spätestens wenn die Anzahl der indizierten Datensätze größer ist, als die Kapazität der Tabelle, werden Kollisionen unvermeidbar. Das bedeutet, dass das Verfahren einen zunehmenden Aufwand zur Kollisionslösung aufwenden muss. Um dies zu vermeiden, wird beim Dynamischen Hashing die Hashtabelle bei Bedarf vergrößert. Dies hat jedoch zwangsläufig Auswirkungen auf den Wertebereich der Hash-Funktion, der nun ebenfalls erweitert werden muss. Eine Änderung der Hash-Funktion wiederum hat jedoch den nachteiligen Effekt, dass sich ebenfalls die Hash-Werte für bereits gespeicherte Daten ändern. Für das dynamische Hashing wurde dafür eigens eine Klasse von Hash-Funktionen entwickelt, deren Wertebereich vergrößert werden kann, ohne die bereits gespeicherten Hash-Werte zu verändern.&lt;br /&gt;
&lt;br /&gt;
==== Vorteile ====&lt;br /&gt;
* Es gibt keine obere Grenze für das Datenvolumen&lt;br /&gt;
* Einträge können ohne Probleme gelöscht werden&lt;br /&gt;
* Adresskollisionen führen nicht zur [[Clusterbildung]].&lt;br /&gt;
&lt;br /&gt;
==== Nachteile ====&lt;br /&gt;
Falls nicht eine ordnungserhaltende Hashfunktion zum Einsatz kam:&lt;br /&gt;
* kein effizientes Durchlaufen der Einträge nach einer Ordnung&lt;br /&gt;
* keine effiziente Suche nach dem Eintrag mit dem kleinsten oder größten Schlüssel&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Hashtabellen werden in praktisch jeder modernen [[Anwendungssoftware|Applikation]] eingesetzt, etwa zur [[Implementierung]] von [[Menge (Datenstruktur)|Mengen (Sets)]] oder [[Cache]]s.&lt;br /&gt;
&lt;br /&gt;
=== Assoziative Arrays ===&lt;br /&gt;
Ein typischer Anwendungsfall sind daneben [[Assoziatives Array|assoziative Arrays]] (auch bekannt als &amp;#039;&amp;#039;Map&amp;#039;&amp;#039;, &amp;#039;&amp;#039;[[Lookup-Tabelle|Lookup Table]]&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Dictionary&amp;#039;&amp;#039; oder &amp;#039;&amp;#039;Wörterbuch&amp;#039;&amp;#039;); das Nachschlagen der mit einem [[Schlüssel (Informatik)|Schlüssel]] assoziierten Daten kann mittels einer Hashtabelle schnell und elegant implementiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Symboltabellen ===&lt;br /&gt;
[[Symboltabelle]]n, wie sie [[Compiler]] oder [[Interpreter]] verwenden, werden meist ebenfalls als Hashtabelle realisiert.&lt;br /&gt;
&lt;br /&gt;
=== Datenbanken ===&lt;br /&gt;
Wichtig sind Hashtabellen auch für [[Datenbank]]en zur Indizierung von Tabellen. Ein [[Hashindex]] kann unter günstigen Bedingungen zu idealen [[Zugriffszeit]]en führen.&lt;br /&gt;
&lt;br /&gt;
Hashtabellen ermöglichen eine sehr schnelle Suche in großen Datenmengen, da mit der Berechnung des [[Hashwert]]es in einem einzigen Schritt die Anzahl der möglichen Zielobjekte eingeschränkt wird. Damit gehören Hashtabellen zu den effizientesten Indexstrukturen.&lt;br /&gt;
&lt;br /&gt;
Ein großer Nachteil ist jedoch die Gefahr der [[Entartung (Informatik)|Entartung]] durch [[Hashtabelle #Kollisionen|Kollisionen]], die bei einem stetigen Wachstum der Datenmenge unausweichlich sind (wenn die Tabelle nicht vergrößert und jedes darin enthaltene Element neu gehasht wird). Daher, wegen ungünstiger IO-Zugriffsmuster, wenn die Hashtabelle auf einem [[Datenträger]] gespeichert ist und der fehlenden Möglichkeit Intervalle gemäß einer [[Ordnungsrelation]] effizient zu [[iterieren]], muss der Einsatz von [[Datenbanksystem]]en gegenüber alternativen Indexdatenstrukturen, wie z.&amp;amp;nbsp;B. [[B+-Baum|B+-Bäumen]], abgewogen werden.&lt;br /&gt;
&lt;br /&gt;
Die meisten Hashfunktionen erlauben &amp;#039;&amp;#039;nicht&amp;#039;&amp;#039; die Bewegung zum nächsten oder vorherigen [[Datensatz]] gemäß einer Ordnungsrelation, da sie gezielt die Daten „mischen“, um sie gleichmäßig im Werteraum zu verteilen. Nur spezielle „ordnungserhaltende“ Hashfunktionen erlauben eine derartige Iteration gemäß ihrer Ordnungsrelation und damit die Abfrage mit Ungleichheitsverknüpfungen („größer als“, „kleiner als“) oder den sortierten Zugriff auf alle Werte.&amp;lt;ref&amp;gt;{{cite web|url=https://cmph.sourceforge.net/concepts.html|title=Minimal Perfect Hash Functions - Introduction|accessdate=2010-11-08|language=Englisch|publisher=[[SourceForge]]|author=Davi de Castro Reis, Djamel Belazzougui, Fabiano Cupertino Botelho}}&amp;lt;/ref&amp;gt; Um solche Verfahren effizient einsetzen zu können, ist meist eine vorherige Analyse der Datenverteilung notwendig. Sie werden daher meist nur in Datenbanksystemen angewendet, die eine solche Analyse auch beispielsweise zur Anfrageoptimierung durchführen.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
Bildlich kann eine Hashtabelle als ein Telefonbuch betrachtet werden. Suchschlüssel sind die Namen, nach denen gesucht werden soll. Als Hash-Funktion wird die Abbildung des Namens auf seinen Anfangsbuchstaben verwendet. Daraus leitet sich im Idealfall genau die Seite des Namens im Telefonbuch ab. Der Idealfall ist aber nur dann gegeben, wenn es zu jedem Anfangsbuchstaben genau einen Namen geben würde. Dies ist offensichtlich falsch (siehe [[Schubfachprinzip]]) und die Folge sind Kollisionen. Als Ausweg kann man versuchen eine geeignetere Hash-Funktion zu finden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [[Bloomfilter]]&lt;br /&gt;
* [[R-Baum]], effektives Indexverfahren für mehrdimensionale Daten&lt;br /&gt;
* [[Verteilte Hashtabelle]]&lt;br /&gt;
* [[Nebenläufige Hashtabelle]]&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=MAURER, Ward Douglas&lt;br /&gt;
   |Titel=Hash Table Methods&lt;br /&gt;
   |Sammelwerk=ACM Computing Surveys (CSUR)&lt;br /&gt;
   |Band=7&lt;br /&gt;
   |Nummer=1&lt;br /&gt;
   |Datum=1975-03&lt;br /&gt;
   |Seiten=5-19&lt;br /&gt;
   |DOI=10.1145/356643.356645&lt;br /&gt;
   |Sprache=en}}&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=LITWIN, Witold&lt;br /&gt;
   |Titel=Linear Hashing: a new tool for file and table addressing&lt;br /&gt;
   |Sammelwerk=IEEE Int. Conf. Very Large Database VLDB&amp;#039;80&lt;br /&gt;
   |Band=6&lt;br /&gt;
   |Datum=1980-10&lt;br /&gt;
   |Seiten=212-223&lt;br /&gt;
   |Online=https://users.ece.northwestern.edu/~peters/references/Linearhash80.pdf&lt;br /&gt;
   |Abruf=2021-03-18&lt;br /&gt;
   |Sprache=en}}&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=CELIS, Pedro; LARSON, Per-Ake; MUNRO, J. Ian&lt;br /&gt;
   |Titel=Robin hood hashing&lt;br /&gt;
   |Sammelwerk=26th Annual Symposium on Foundations of Computer Science (SFCS&amp;#039;1985)&lt;br /&gt;
   |Datum=1985&lt;br /&gt;
   |Seiten=281-288&lt;br /&gt;
   |DOI=10.1109/SFCS.1985.48&lt;br /&gt;
   |Sprache=en}}&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=PAGH, Rasmus; RODLER, Flemming Friche&lt;br /&gt;
   |Titel=Cuckoo hashing&lt;br /&gt;
   |Sammelwerk=Journal of Algorithms&lt;br /&gt;
   |Band=51&lt;br /&gt;
   |Nummer=2&lt;br /&gt;
   |Datum=2004&lt;br /&gt;
   |Seiten=122-144&lt;br /&gt;
   |DOI=10.1016/j.jalgor.2003.12.002&lt;br /&gt;
   |Sprache=en}}&lt;br /&gt;
* {{Literatur&lt;br /&gt;
   |Autor=BURKHARD, Walter A.&lt;br /&gt;
   |Titel=Double hashing with passbits&lt;br /&gt;
   |Sammelwerk=Information processing letters&lt;br /&gt;
   |Sprache=en&lt;br /&gt;
   |Band=96&lt;br /&gt;
   |Nummer=5&lt;br /&gt;
   |Datum=2005-12-16&lt;br /&gt;
   |Seiten=162-166&lt;br /&gt;
   |DOI=10.1016/j.ipl.2005.08.005}}&lt;br /&gt;
* [[Thomas H. Cormen]], [[Charles E. Leiserson]], [[Ronald L. Rivest]]: &amp;#039;&amp;#039;Introduction to Algorithms&amp;#039;&amp;#039;. 1184 Seiten; The MIT Press 2001, ISBN 0-262-53196-8.&lt;br /&gt;
* [[Alfons Kemper]], André Eickler: [http://www-db.in.tum.de/research/publications/books/DBMSeinf/ &amp;#039;&amp;#039;Datenbanksysteme – Eine Einführung.&amp;#039;&amp;#039;] 7. Auflage, Oldenbourg Verlag 2009, ISBN 3-486-57690-9. Seite 220f&lt;br /&gt;
* Christian Ullenboom: &amp;#039;&amp;#039;Java ist auch eine Insel&amp;#039;&amp;#039;, 1444 Seiten; Galileo Press 2007, ISBN 3-89842-838-9; [http://www.galileocomputing.de/openbook/javainsel6/ online] als [[OpenBook (Buch)|Openbook]] verfügbar.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [https://libhashish.sourceforge.net/ Umfangreiche Hashbibliothek mit weitreichender Analysefunktionalität]&lt;br /&gt;
* [http://www.it-c.dk/people/pagh/papers/cuckoo-undergrad.pdf Cuckoo Hashing] (englisch, PDF, 169&amp;amp;nbsp;KiB)&lt;br /&gt;
* [https://everythingcomputerscience.com/discrete_mathematics/Data_Structures/Hash_Table.html Hash Table]&lt;br /&gt;
&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Normdaten|TYP=s|GND=1046573225}}&lt;br /&gt;
[[Kategorie:Datenstruktur]]&lt;br /&gt;
[[Kategorie:Datenbankindex]]&lt;br /&gt;
[[Kategorie:Hash]]&lt;br /&gt;
[[Kategorie:Suchalgorithmus]]&lt;/div&gt;</summary>
		<author><name>imported&gt;SchlurcherBot</name></author>
	</entry>
</feed>