Skip to content
Snippets Groups Projects
Commit 67329e7f authored by Florian Unger's avatar Florian Unger
Browse files

Tippfehler ausgebessert, Löschvorgang bei offener Addressierung genauer beschrieben.

parent 6231b88d
No related branches found
No related tags found
No related merge requests found
......@@ -56,7 +56,8 @@ und können.
Die Idee liegt darin, Elemente, die zum gleichen Index führen, als verkette
Liste zu organisieren. Das heißt, dass in der Hashtabelle in Feld $j$ nur der Kopf einer Liste steht.
Konzeptionell ist eine Hashtabelle mit Überläuferlisten der Größe $m$ also eigentlich kein Array, sondern eine
Komposition aus einer $m-$wertigen Hashfunktion $h$ und $m$ Listen: $\mathcal{T} = (h, \mathcal{L}_0, \dots, \mathcal{L}_{m-1}$.
Komposition aus einer $m-$wertigen Hashfunktion $h$ und $m$ Listen: $\mathcal{T} = (h, \mathcal{L}_0, \dots,
\mathcal{L}_{m-1})$.
In einer konkreten Implementierung, insbesondere dann, wenn die Kollisionen nur sehr selten auftreten, können wir ein
Array nutzen und die Listen nur im Kollisionsfall dazuschalten.
......@@ -77,7 +78,7 @@ Die drei nötigen Funktionen zur Lösung des Wörterbuchproblems können folgend
Im Laufe der Zeit werden in unser Hashtable $\mathcal{T}$ Elemente eingefügt und gelöscht, die derzeitige Anzahl der
Elemente bezeichnen wir mit $n \in \mathbb{N}$. Wir betrachten nun den durchschnittlichen Aufwand beim Suchen in
Abhängigkeit von dem Belegungsfaktor $α$.
Wir nehmen an, dass wir eine ideale Hashfunktion $h_{\text{i}}$ vorliegen haben.
Wir nehmen an, dass wir eine ideale Hashfunktion $h$ vorliegen haben.
Der worst case wäre, dass alle Elemente
durch großes Pech beim hashen in einer einzigen Überläuferliste gespeichert sind, welche wir mit $Θ(n)$ Aufwand linear durchsuchen müssen. Dieser
......@@ -110,7 +111,7 @@ Es gibt drei übliche Sondierungsverfahren, das linear probing, quadratic probin
\]
Diese Methode ist sehr schnell, aber es kommt zu einem sogenannten Primärcluster: Benachbarte Positionen sind mit
höherer Wahrscheinlichkeit belegt. Je nach Hashfunktion $h$ kann das ein großer Nachteil sein.
\item Qudaratisches Sondieren: Indem man die Sprünge beim Versuch eine freie Stelle zu finden quadratisch ansteigen lässt, kann man den primären
\item Qudratisches Sondieren: Indem man die Sprünge beim Versuch eine freie Stelle zu finden quadratisch ansteigen lässt, kann man den primären
Ballungseffekt verhindern. Die derivierte Hashfunktion $h'$ ist also
\[
h'(s,i) = \left(h(s) + c_2 i^2 + c_1 i \right) \text{ mod } m.
......@@ -156,7 +157,7 @@ Man beachte, dass die asymptotische Zeit zum Einfügen nun nichtmehr konstant is
\For{$i \leftarrow 0$ \KwTo $m - 1$}{
$j \leftarrow h'(s,i)$ \;
\uIf{$\texttt{key}(\mathcal{A}[j]) = s$}{
\KwRet $\mathcal{T}$
\KwRet $(s,d)$
}
\uElseIf{$\mathcal{A}[j] = \texttt{null}$}{
\texttt{error}(Key $s$ not found) \;
......@@ -166,7 +167,8 @@ Man beachte, dass die asymptotische Zeit zum Einfügen nun nichtmehr konstant is
\end{algorithm}
Der Algorithmus für das Löschen beginnt wie bei Überläuferliste erst aus dem Suchen. Wird ein Element mit passendem
Schlüssel gefunden, wird das Arrayfeld mit $\texttt{null}$ überschrieben.
Schlüssel gefunden, so wird der letzte Eintrag mit dem gleichen Hash an diese Stelle geschrieben und das nun nichtmehr
benötigte Arrayfeld durch überschreiben mit $\texttt{null}$ freigegeben.
Eine Hashtabelle dieser Art definiert sich also mit $\mathcal{T} = (h', \mathcal{A})$, wobei $\mathcal{A}$ ein
gewöhnliches Array der Länge $m$ ist.
......@@ -174,7 +176,7 @@ gewöhnliches Array der Länge $m$ ist.
Wieder wollen wir die Aufwände für das Suchen betrachten. Wir konzentrieren uns auf den Fall, dass das gesuchte Elemente
nicht in der Tabelle vorhanden ist. In diesem Fall ist der Aufwand für das Suchen gleich dem Aufwand für das Einfügen.
Wie zuvor ist der Belegungsfaktor $α$ ausschlaggebend. In Fall von offener Adressierung gilt stets $α \leq 1$, wir
wollen hier aber $α < 1$ annehmen, da sonst die Aufwände ins unendliche Wachsen.
wollen hier aber $α < 1$ annehmen, da sonst die Aufwände ins Unendliche wachsen.
Weiterhin nehmen wir wieder die Verwendung einer idealen Hashfunktion an:
Ist unser Element nicht vorhanden, so ist (tautologisch) jeder Versuch bis auf den letzten besetzt. Sei $p_i$ die Wahrscheinlichkeit, dass genau $i$ Versuche besetzt sind.
......@@ -220,7 +222,7 @@ Bisher haben wir nur eine ideale Hashfunktion benutzt, die aber so ein theoretis
reale Hashfunktionen:
\begin{itemize}
\item Die Identitätsfunktion: Ist der Schlüssel $s$ bereits eine Zahl in $\{0,\dots,m-1\}$, sowie gleichverteilt und Kollisionsarm, so kann man als
\item Die Identitätsfunktion: Ist der Schlüssel $s$ bereits eine Zahl in $\{0,\dots,m-1\}$, sowie gleichverteilt und kollisionsarm, so kann man als
Hashfunktion einfach die Identität $h(s) = s$ nehmen. Das ist zweifelsohne am schnellsten.
\item Division mit Rest:
\[
......@@ -236,7 +238,7 @@ reale Hashfunktionen:
\]
Diese Hashfunktion ist immernoch sehr schnell und liefert bei guter Wahl von $A$ ausreichend gute Resultate.
\item Fibonacci-Hash: Das ist die Multiplikationsmethode mit $A = \frac{\sqrt{5} - 1}{2} \approx 0.6180339\dots$
verwendet. Durch seine irrationalität erreicht er eine gute Verteilung.
verwendet. Durch seine Irrationalität erreicht er eine gute Verteilung.
\item Kryptographische Hashfunktionen: Im Prinzip kann auch eine beliebige kryptographische Hashfunktion genutzt
werden. Diese haben nahezu ideale Eigenschaften (Gleichverteilung, Schwierigkeit eine Hashkollision zu erzwingen, etc), sind aber
aufgrund ihres Designs auch sehr rechenintensiv. Außerdem gibt es Einschränkungen in der Größe von $m$.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment