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

Operationen auf Binärbäumen in rekursiver Formulierung

parent 49ffbcc8
No related branches found
No related tags found
No related merge requests found
...@@ -193,6 +193,152 @@ nächstgrößere und nächstkleinere Element finden, solange der Baum nicht allz ...@@ -193,6 +193,152 @@ nächstgrößere und nächstkleinere Element finden, solange der Baum nicht allz
Alle Funktionen laufen dabei in $\mathcal{O}(h)$, im Idealfall also $\mathcal{O}(\log_2 n)$. Im schlechtesten Fall, in Alle Funktionen laufen dabei in $\mathcal{O}(h)$, im Idealfall also $\mathcal{O}(\log_2 n)$. Im schlechtesten Fall, in
dem der Baum zu einer doppelt verketteten Liste degeneriert ist, liegt die Laufzeit in $\mathcal{O}(n)$. dem der Baum zu einer doppelt verketteten Liste degeneriert ist, liegt die Laufzeit in $\mathcal{O}(n)$.
Um die gängisten Operationen zu beschreiben, adaptieren wir folgende Perspektive auf Binäre Suchbäume:
Ein Binärer Suchbaum über einen Datentyp $D$ mit totaler Ordnung ist entweder leer, oder besteht aus einem linken
Teilbaum, der Information im Node und einem rechten Teilbaum:
\begin{align*}
\text{BST}\; D &= ε\ |\; \text{BST}\; D\quad D\quad \text{BST}\; D \\
\mathcal{B}\quad &= ε\ |\;\quad l\qquad \ \ \ x\; \ \qquad r
\end{align*}
In dieser Notation beschreiben wir nun kombat die gängisten Operationen auf binären Suchbäumen in rekursiver Form:
Die Höhe ist $1$ + die Höhe des größeren Teilbaums:
\begin{align*}
\texttt{height}(ε) &= 0 \\
\texttt{height}(l\; x\; r) &= 1 + \max(\texttt{height}(l), \texttt{height}(r)).\\
\end{align*}
Gesucht wird analog zur Binärsuche:
\begin{align*}
\texttt{search}(ε,k) &= \texttt{error: Key not found} \\
\texttt{search}(l\; (k',v')\; r, k) &=
\begin{cases}
\texttt{search}(l, k) &\text{if } k < k'\\
(k',v') &\text{if } k = k'\\
\texttt{search}(r, k) &\text{if } k > k'\\
\end{cases}\\
\end{align*}
Das Minimum findet man, indem man immer nach links geht:
\begin{align*}
\texttt{min}(ε) &= \texttt{error: Minimum in empty tree ill-defined} \\
\texttt{min}\; x\; r) &= x \\
\texttt{min}(l\; x\; r) &= \texttt{min}(l) \\
\end{align*}
\paragraph{Einfügen in BST}
Das Einfügen in einen Binären Suchbaum läuft analog zum Suchen - ist der einzufügende Wert größer, so schaut man
rekursiv im rechten Teilbaum, ist er kleiner, im linken. Erst dann, wenn man auf einen leeren Teilbaum stößt, hat man
einen leeren Platz gefunden:
\begin{align*}
\texttt{insert}(ε,(k,v)) &= ε\; (k,v)\; ε \\
\texttt{insert}(l\; (k',v')\; r, (k,v)) &=
\begin{cases}
\texttt{insert}(l, (k,v))\; (k',v')\; r &\text{if } k < k'\\
l\; (k,v)]l r &\text{if } k = k'\\
l\; (k',v')\; \texttt{insert}(r, (k,v)) &\text{if } k > k'\\
\end{cases}\\
\end{align*}
\paragraph{Löschen aus BST}
Beim Löschen müssen wir unter drei verschiedenen Fällen unterscheiden: Der zu löschende Knoten ist ein Blatt, der zu
löschende Knoten hat genau ein Kind, der zu löschende Knoten hat zwei Kinder.
\begin{figure}[h!]
\centering
\input{bilder/BST_delete}
\caption{Fallunterscheidung bei der Löschung von $x$: Kein Kind, Ein Kind, zwei Kinder. Der modifizierte Teilbaum $c'$
ist $c$ ohne \texttt{succ}(x), den Nachfolger von $x$.}
\label{fig:BST_delete}
\end{figure}
Wir formalisieren es folgendermaßen:
\begin{align*}
\texttt{fad}(ε,x) &= ε \\
\texttt{fad}(l\; x'\; r, x) &=
\begin{cases}
\texttt{fad}(l,x)\; x'\; r &\text{if } x < x'\\
\texttt{delete}(l\; x'\; l, x) &\text{if } k = k'\\
l\; x'\; \texttt{fad}(r,x) &\text{if } x > x'\\
\end{cases}\\
\end{align*}
wobei \texttt{delete} nun die drei Fälle in Abbildung \ref{fig:BST_delete} abdeckt:
\begin{align*}
\texttt{delete}\;x\;ε,x) &= ε \\
\texttt{delete}\;x\;r,x) &= r \\
\texttt{delete}(l\;x\;ε,x) &= r \\
\texttt{delete}(l\;x\;r,x) &= l\; t\; \texttt{delete}(r,t) \\
\text{wobei }\quad t &= \texttt{min}(r)
\end{align*}
\subsection{Die zu erwartende Höhe von BST bei zufälligem Einfügen*}
Ein Binärbaum mit $n$ Elementen kann eine Höhe $h$ zwischen $\ceil{\log_2(n+1)} ≤ h ≤ n$ haben.
Wenn wir einen komplett leeren Binärbaum mit vorgegebenen Daten befüllen, tritt die untere Grenze beispielsweise dann,
wenn wir rekursiv immer wieder den Median der vom Median getrennten Teilarrays einfügen. Die obere Grenze wird z.B.
erreicht, wenn wir die Elemente gemäß ihrer Ordnung einfügen.
Da die Laufzeit aller Algorithmen auf Binären Suchbäumen direkt von der Höhe abhängt, stellt sich die Frage:
Was ist die zu erwartende Höhe eines Binärbaums, wenn man (eindeutige) Elemente in einer zufälligen Reihenfolge einfügt?
\begin{proposition}
Werde $π \in S_n$, eine Permutation von $n$ Elementen (d.h. die Elemente $\{1,\cdots,n\}$ in einer zufälligen Reihenfolge
ohne Wiederholungen), in einen initial leeren Binärer Suchbaum eingefügt. Sei $H_n$ die Zufallsvariable,
die die Höhe dieses zufällig befüllten Baumes beschreibt.
Dann wächst der Erwartungswert von $H_n$ logarithmisch, d.h.:
\[
\mathbb{E}[H_n] \in Θ(\log n).
\]
\label{prop:BST_average_case_wachstum}
\end{proposition}
\begin{proof}
Die untere Grenze ist klar, da wie eingangs beschrieben die Höhe eines Baumes immer in $Ω(\log n)$ liegt.
In einem Binären Suchbaum sind alle Elemente links vom derzeitigen Knoten kleiner und alle Elemente rechts größer.
Wird ein Element $i$ gezogen, befinden sich am Ende $i-1$ Elemente im linken Teilbaum und $n-i$
Elemente im rechten Teilbaum.
Die Höhe eines nichtlehren Baumes ist 1 + die Höhe des größten Teilbauem.
Unter der Annahme, dass alle Elemente gleichwahrscheinlich gezogen werden, ist der Erwartungswert von $H_n$ einfach nur der
Durchschnitt aller möglichen Fälle:
\begin{equation*}
\mathbb{E}[H_n] = \frac{1}{n} \sum_{i=1}^n \mathbb{E}[1 + \max(H_{i-1}, H_{n-i})].
\label{eq:h_n_rek}
\end{equation*}
Wir betrachten nun $Y_n = 2^{H_n}$: Wenn wir zeigen können, dass $\mathbb{E}[Y_n] \in \mathcal{O}(n^a)$, so folgt
daraus das $\mathbb{E}[H_n] \in \mathcal{O}(a \log n) = \mathcal{O}(\log n)$.
In dieser exponentiellen Darstellung wird exponentielle Höhe nun durch \\$Y_n = 2 \max(Y_{i-1},Y_{n-1})$ beschrieben,
analog verhält sich der Erwartungswert von $Y_n$:
\begin{equation*}
\mathbb{E}[Y_n] = \frac{2}{n} \sum_{i=1}^n \mathbb{E}[\max(Y_{i-1}, Y_{n-i})].
\label{eq:EW_Yn_1}
\end{equation*}
Wobei wir durch die Abschätzung $\mathbb{E}[\max(X,Y)]\mathbb{E}[X] + \mathbb{E}[Y]$ (gültig für nichtnegative
Zufallsvariablen $X$ und $Y$) und der Symmetrie der Summenterme weiter zu
\[
\mathbb{E}[Y_n]\frac{2}{n} \sum_{i=1}^n (\mathbb{E}[Y_{i-1}] + \mathbb{E}[Y_{n-i}]) = \frac{4}{n}
\sum_{i=0}^{n-1}\mathbb{E}[ Y_i ]
\]
vereinfachen.
Setzte $Z_n = \mathbb{E}[Y_n]$, die resultierende Rekurrenzformel lässt sich wie folgt umstellen:
\begin{align*}
Z_n &= \frac{4}{n} \sum_{i=0}^{n-1} Z_i \\
&= \frac{4}{n} (Z_{n-1} + Z_{n-2} + \cdots + Z_0) \\
&= \frac{4}{n} (Z_{n-1} + \frac{n-1}{4} Z_{n-1}) \\
&= \frac{4}{n} (1+\frac{n-1}{4}) Z_{n-1} \\
&= \frac{4 + n -1}{n} Z_{n-1} \\
&= \frac{3+n}{n} Z_{n-1},
\end{align*}
welche die Lösung $Z_n = c \cdot (n+3)(n+2)(n+1) \in \mathcal{O}(n^3)$ besitzt. Da
\[
\log n^3 = 3 \log n \in \mathcal{O}(\log n),
\]
gilt $\mathbb{E}[H_n] \in \mathcal{O}(\log n)$.
\end{proof}
\paragraph{Suchen in Binärbäumen:} \paragraph{Suchen in Binärbäumen:}
Der Algorithmus ähnelt einer Binärsuche. Der Algorithmus ähnelt einer Binärsuche.
......
\tikzsetnextfilename{BST_delete}
\begin{tikzpicture}[
treenode/.style = {align=center,inner sep=0pt, text centered, font=\sffamily},
fullnode/.style = {treenode, circle, draw, text width=1.5em},
subtree/.style = {treenode, circle, text width=1.5em},
level/.style={sibling distance = 5cm/#1,
level distance = 1.5cm},
scale=0.4
]
\begin{scope} [local bounding box=fall1] % case 1
\begin{scope}[local bounding box=f1v]
\node[fullnode] (x) {$x$}
child{ node [subtree] (lε) {$ε$}}
child{ node [subtree] (rε) {$ε$}}
;
\end{scope}
\begin{scope}[shift={(6,-0.8)}, local bounding box=f1n]
\node[subtree] (tε) {$ε$};
\end{scope}
\draw [->,decorate,decoration={snake,amplitude=.3mm,segment length=2mm,post length=1mm}] (f1v) -- node[below]{\tiny \texttt{delete}} (f1n);
\end{scope}
\begin{scope} [shift={(14,0.80)}, local bounding box=fall2] % case 2
\begin{scope}[local bounding box=f2v]
\node[fullnode] (x) {$x$}
child{ node [subtree] (lε) {$ε$}}
child{ node [fullnode] (ry) {$y$}
child{ node [subtree] (la) {$a$}}
child{ node [subtree] (rb) {$b$}}}
;
\end{scope}
\begin{scope}[shift={(10,-0.7)}, local bounding box=f2n]
\node[fullnode] (ty) {$y$}
child{ node [subtree] (la) {$a$}}
child{ node [subtree] (rb) {$b$}}
;
\end{scope}
\draw [->,decorate,decoration={snake,amplitude=.3mm,segment length=2mm,post length=1mm}] (f2v) -- node[below]{\tiny \texttt{delete}} (f2n);
\end{scope}
\begin{scope} [shift={(7,-6)}, local bounding box=fall3] % case 3
\begin{scope}[local bounding box=f3v]
\node[fullnode] (x) {$x$}
child{ node [fullnode] (ry) {$y$}
child{ node [subtree] (la) {$a$}}
child{ node [subtree] (rb) {$b$}}}
child{ node [fullnode] (lz) {$z$}
child{ node [subtree] (lc) {$c$}}
child{ node [subtree] (rd) {$d$}}}
;
\end{scope}
\begin{scope}[shift={(11,-0)}, local bounding box=f3n]
\node[fullnode] (ty) {$\texttt{succ}(x)$}
child{ node [fullnode] (ry) {$y$}
child{ node [subtree] (la) {$a$}}
child{ node [subtree] (rb) {$b$}}}
child{ node [fullnode] (lz) {$z$}
child{ node [subtree] (lc') {$c'$}}
child{ node [subtree] (rd) {$d$}}}
;
\end{scope}
\draw [->,decorate,decoration={snake,amplitude=.3mm,segment length=2mm,post length=1mm}] (f3v) -- node[below]{\tiny \texttt{delete}} (f3n);
\end{scope}
\end{tikzpicture}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment