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

alten node-orientierten code in appendix verschoben

parent 968821ca
No related branches found
No related tags found
No related merge requests found
...@@ -339,136 +339,3 @@ Was ist die zu erwartende Höhe eines Binärbaums, wenn man (eindeutige) Element ...@@ -339,136 +339,3 @@ Was ist die zu erwartende Höhe eines Binärbaums, wenn man (eindeutige) Element
gilt $\mathbb{E}[H_n] \in \mathcal{O}(\log n)$. gilt $\mathbb{E}[H_n] \in \mathcal{O}(\log n)$.
\end{proof} \end{proof}
\paragraph{Suchen in Binärbäumen:}
Der Algorithmus ähnelt einer Binärsuche.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{\texttt{search}($k, v$)}
\KwIn{A node $k$ and and a data value $v$}
\KwOut{The node $k'$ of the subtree of $k$ which has $\texttt{data}(k') = v$}
\eIf{$k \neq \texttt{void\_node}$ and $\texttt{data}(k) \neq \texttt{void}$}{
\KwRet $k$ \;
}{
\eIf{$v \leq \texttt{data}(k)$}{
$\texttt{search}(\texttt{left}(k), v)$ \;
}{
$\texttt{search}(\texttt{right}(k), v)$ \;
}
}
\end{algorithm}
\paragraph{Finden des Minimums und Maximums in $\mathcal{B}$}
Hier gehen wir so lange nach links, bis es kein linkes Kind mehr gibt. Da wir nach symmetrischer Reihenfolge geordnet
sind, finden wir damit das Minimum des Baums, wenn wir $\texttt{minimum}(\texttt{root}(\mathcal{B}))$ aufrufen.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{\texttt{minimum}($k$)}
\KwIn{A node $k$ of a binary search tree}
\KwOut{The node with the smallest value within the subtree of $k$}
\eIf{$\texttt{left}(k)$ = \texttt{void\_node}}{
\KwRet $k$ \;
}{
\KwRet $\texttt{minimum}(\texttt{left}(k))$ \;
}
\end{algorithm}
Diese Rekursion ist eine Endrekursion und braucht keinen zusätzlichen Speicher. Die Laufzeit ist von
$\mathcal{O}(h)$ begrenzt.
Analog finden wir das Maximum mit $\texttt{maximum}(\texttt{root}(\mathcal{B}))$ wenn wir immer nach rechts laufen.
\paragraph{Finden des Vorgängers/Nachfolgers eines Knotens:}
Übungsaufgabe.
\paragraph{Einfügen in den Binärbaum:}
In den Binärbaum $B$ wird der Wert $w$ eingefügt. Wir müssen dabei darauf achten, dass der Wert an der passenden Stelle
eingefügt wird, also der Baum in symmetrische Reihenfolge weiterhin sortiert bleibt.
Wir gehen also immer dann nach links, wenn der Wert im Knoten größer ist und andernfalls rechts entlang.
\begin{algorithm}[H]
\SetArgSty{textrm}
\SetNlSty{texttt}{[}{]}
\caption{\texttt{insert}($B, v$)}
\KwIn{A binary tree $\mathcal{B}$ and a new value $v$}
\KwOut{Side effects in $\mathcal{M}$}
$x_\text{last} \leftarrow \texttt{void\_node}$ \;
$x \leftarrow \texttt{root}(\mathcal{B})$ \;
\While{$x \neq \texttt{void\_node}$}{
$x_\text{last} \leftarrow x$ \;
\eIf{$v < \texttt{data}(x)$}{
$x \leftarrow \texttt{left}(x)$ \;
}{
$x \leftarrow \texttt{right}(x)$ \;
}
}
%TODO: void_node nicht länger als leeren Knoten missbrauchen
$\texttt{data}(x) \leftarrow v$ \;
$\texttt{parent}(x) \leftarrow x_\text{last}$ \;
$\texttt{change\_parents\_reference}(\mathcal{B}, x, x)$ \;
\end{algorithm}
Wobei folgende Hilfsfunktion den richtigen Kindpointer von einem alten Kindknoten auf einen neuen umbiegt. In unserem
Fall benutzten wir sie nur, um eine Referenz von $\texttt{parent}(x)$ auf $x$ zu legen.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{$\texttt{change\_parents\_reference}(B, k, t)$}
\KwIn{A binary tree $\mathcal{B}$, the old child node $k$ and the new target child node~$t$}
\KwOut{Side effects in $\mathcal{B}$: The parent of $k$ changes the respective child pointer from $k$ to $t$. In case
of $k$ being the root, $t$ is set as the new root.}
$p \leftarrow \texttt{parent}(k)$ \;
\uIf{$p = \texttt{void\_node}$}{
$\texttt{root}(\mathcal{B}) \leftarrow t$ \;
}
\uElseIf{$\texttt{data}(k) < \texttt{data}(p)$}{
$\texttt{left}(p) \leftarrow t$ \;
}
\Else{
$\texttt{right}(p) \leftarrow t$ \;
}
\end{algorithm}
\paragraph{Löschen eines Werts:}
Soll der Knoten $k$ gelöscht werden, müssen drei Fälle unterschieden werden, damit die Sortierung erhalten bleibt:
\begin{enumerate}
\item Ist $k$ kinderlos, so entfernen wird den Knoten, indem wir an der passenden Stelle des Elternknotens die
Referenz auf $\texttt{void}$ umschreiben.
\item Hat $k$ hat nur ein Kind, $c$, so entfernen wir den Knoten $k$ indem wir $k$ überspringen. Dazu biegen wir
die Referenz des Elternknotens von $k$ auf das Kind von $c$ um.
\item Im letzten Fall hat $k$ hat zwei Kinder. Wir ersetzen die Daten von $k$ durch die Daten des nächstgrößeren
Knotens $t$ und löschen dann den Knoten $t$. Da dieser nur maximal ein Kind hat (er kann kein linkes Kind haben,
sonst wäre dass das nächstgrößere) terminert dieser rekursive Aufruf von $\texttt{delete}$ nach einem Schritt, da
wir einem der letzten beiden Fälle landen. Ist das Verschieben der Daten sehr teuer, so können wir alternativ auch
alle Pointer so umbiegen, dass $t$ in der Baumstruktur den Platz von $k$ einnimmt (nicht gezeigt).
\end{enumerate}
\begin{algorithm}[H]
\SetArgSty{textrm}
\SetNlSty{texttt}{[}{]}
\caption{\texttt{delete}($\mathcal{B}, k$)}
\KwIn{A binary tree $\mathcal{B}$ and the unwanted node $k$}
\KwOut{Side effects in $\mathcal{M}$: The node $k$ is removed from $\mathcal{B}$, but child nodes of $k$ are
preserved.}
\uIf{$\texttt{left}(k) = \texttt{void\_node} \text{ and } \texttt{right}(k) = \texttt{void\_node}$}{
$\texttt{change\_parents\_reference}(\mathcal{B}, k, \texttt{void\_node})$ \;
}
\uElseIf{$\texttt{left}(k) \neq \texttt{void\_node} \text{ XOR } \texttt{right}(k) \neq \texttt{void\_node}$}{
\eIf{$\texttt{left}(k) \neq \texttt{void\_node}$}{
$c \leftarrow \texttt{left}(k)$ \;
}{
$c \leftarrow \texttt{right}(k)$ \;
}
$\texttt{change\_parents\_reference}(\mathcal{B}, k, c)$ \;
}
\Else{
$t \leftarrow \texttt{minimum}(\texttt{right}(k))$ \;
$\texttt{data}(k) \leftarrow \texttt{data}(t)$ \;
$\texttt{delete}(\mathcal{B}, t)$ \;
}
\end{algorithm}
\chapter{Node-orientierter Pseudocode für BST}
Dieses Kapitel beschreibt die üblichen Operationen von Binary Search Trees in imperativer, node-orientierter Variante.
\paragraph{Suchen in Binärbäumen:}
Der Algorithmus ähnelt einer Binärsuche.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{\texttt{search}($k, v$)}
\KwIn{A node $k$ and and a data value $v$}
\KwOut{The node $k'$ of the subtree of $k$ which has $\texttt{data}(k') = v$}
\eIf{$k \neq \texttt{void\_node}$ and $\texttt{data}(k) \neq \texttt{void}$}{
\KwRet $k$ \;
}{
\eIf{$v \leq \texttt{data}(k)$}{
$\texttt{search}(\texttt{left}(k), v)$ \;
}{
$\texttt{search}(\texttt{right}(k), v)$ \;
}
}
\end{algorithm}
\paragraph{Finden des Minimums und Maximums in $\mathcal{B}$}
Hier gehen wir so lange nach links, bis es kein linkes Kind mehr gibt. Da wir nach symmetrischer Reihenfolge geordnet
sind, finden wir damit das Minimum des Baums, wenn wir $\texttt{minimum}(\texttt{root}(\mathcal{B}))$ aufrufen.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{\texttt{minimum}($k$)}
\KwIn{A node $k$ of a binary search tree}
\KwOut{The node with the smallest value within the subtree of $k$}
\eIf{$\texttt{left}(k)$ = \texttt{void\_node}}{
\KwRet $k$ \;
}{
\KwRet $\texttt{minimum}(\texttt{left}(k))$ \;
}
\end{algorithm}
Diese Rekursion ist eine Endrekursion und braucht keinen zusätzlichen Speicher. Die Laufzeit ist von
$\mathcal{O}(h)$ begrenzt.
Analog finden wir das Maximum mit $\texttt{maximum}(\texttt{root}(\mathcal{B}))$ wenn wir immer nach rechts laufen.
\paragraph{Finden des Vorgängers/Nachfolgers eines Knotens:}
Übungsaufgabe.
\paragraph{Einfügen in den Binärbaum:}
In den Binärbaum $B$ wird der Wert $w$ eingefügt. Wir müssen dabei darauf achten, dass der Wert an der passenden Stelle
eingefügt wird, also der Baum in symmetrische Reihenfolge weiterhin sortiert bleibt.
Wir gehen also immer dann nach links, wenn der Wert im Knoten größer ist und andernfalls rechts entlang.
\begin{algorithm}[H]
\SetArgSty{textrm}
\SetNlSty{texttt}{[}{]}
\caption{\texttt{insert}($B, v$)}
\KwIn{A binary tree $\mathcal{B}$ and a new value $v$}
\KwOut{Side effects in $\mathcal{M}$}
$x_\text{last} \leftarrow \texttt{void\_node}$ \;
$x \leftarrow \texttt{root}(\mathcal{B})$ \;
\While{$x \neq \texttt{void\_node}$}{
$x_\text{last} \leftarrow x$ \;
\eIf{$v < \texttt{data}(x)$}{
$x \leftarrow \texttt{left}(x)$ \;
}{
$x \leftarrow \texttt{right}(x)$ \;
}
}
%TODO: void_node nicht länger als leeren Knoten missbrauchen
$\texttt{data}(x) \leftarrow v$ \;
$\texttt{parent}(x) \leftarrow x_\text{last}$ \;
$\texttt{change\_parents\_reference}(\mathcal{B}, x, x)$ \;
\end{algorithm}
Wobei folgende Hilfsfunktion den richtigen Kindpointer von einem alten Kindknoten auf einen neuen umbiegt. In unserem
Fall benutzten wir sie nur, um eine Referenz von $\texttt{parent}(x)$ auf $x$ zu legen.
\begin{algorithm}[H]
\SetNlSty{texttt}{[}{]}
\caption{$\texttt{change\_parents\_reference}(B, k, t)$}
\KwIn{A binary tree $\mathcal{B}$, the old child node $k$ and the new target child node~$t$}
\KwOut{Side effects in $\mathcal{B}$: The parent of $k$ changes the respective child pointer from $k$ to $t$. In case
of $k$ being the root, $t$ is set as the new root.}
$p \leftarrow \texttt{parent}(k)$ \;
\uIf{$p = \texttt{void\_node}$}{
$\texttt{root}(\mathcal{B}) \leftarrow t$ \;
}
\uElseIf{$\texttt{data}(k) < \texttt{data}(p)$}{
$\texttt{left}(p) \leftarrow t$ \;
}
\Else{
$\texttt{right}(p) \leftarrow t$ \;
}
\end{algorithm}
\paragraph{Löschen eines Werts:}
Soll der Knoten $k$ gelöscht werden, müssen drei Fälle unterschieden werden, damit die Sortierung erhalten bleibt:
\begin{enumerate}
\item Ist $k$ kinderlos, so entfernen wird den Knoten, indem wir an der passenden Stelle des Elternknotens die
Referenz auf $\texttt{void}$ umschreiben.
\item Hat $k$ hat nur ein Kind, $c$, so entfernen wir den Knoten $k$ indem wir $k$ überspringen. Dazu biegen wir
die Referenz des Elternknotens von $k$ auf das Kind von $c$ um.
\item Im letzten Fall hat $k$ hat zwei Kinder. Wir ersetzen die Daten von $k$ durch die Daten des nächstgrößeren
Knotens $t$ und löschen dann den Knoten $t$. Da dieser nur maximal ein Kind hat (er kann kein linkes Kind haben,
sonst wäre dass das nächstgrößere) terminert dieser rekursive Aufruf von $\texttt{delete}$ nach einem Schritt, da
wir einem der letzten beiden Fälle landen. Ist das Verschieben der Daten sehr teuer, so können wir alternativ auch
alle Pointer so umbiegen, dass $t$ in der Baumstruktur den Platz von $k$ einnimmt (nicht gezeigt).
\end{enumerate}
\begin{algorithm}[H]
\SetArgSty{textrm}
\SetNlSty{texttt}{[}{]}
\caption{\texttt{delete}($\mathcal{B}, k$)}
\KwIn{A binary tree $\mathcal{B}$ and the unwanted node $k$}
\KwOut{Side effects in $\mathcal{M}$: The node $k$ is removed from $\mathcal{B}$, but child nodes of $k$ are
preserved.}
\uIf{$\texttt{left}(k) = \texttt{void\_node} \text{ and } \texttt{right}(k) = \texttt{void\_node}$}{
$\texttt{change\_parents\_reference}(\mathcal{B}, k, \texttt{void\_node})$ \;
}
\uElseIf{$\texttt{left}(k) \neq \texttt{void\_node} \text{ XOR } \texttt{right}(k) \neq \texttt{void\_node}$}{
\eIf{$\texttt{left}(k) \neq \texttt{void\_node}$}{
$c \leftarrow \texttt{left}(k)$ \;
}{
$c \leftarrow \texttt{right}(k)$ \;
}
$\texttt{change\_parents\_reference}(\mathcal{B}, k, c)$ \;
}
\Else{
$t \leftarrow \texttt{minimum}(\texttt{right}(k))$ \;
$\texttt{data}(k) \leftarrow \texttt{data}(t)$ \;
$\texttt{delete}(\mathcal{B}, t)$ \;
}
\end{algorithm}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment