Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
Datenstrukturen und Algorithm Skript
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Cemal, Mevludin
Datenstrukturen und Algorithm Skript
Commits
ce29f15c
Commit
ce29f15c
authored
Jun 18, 2022
by
Florian Unger
Browse files
Options
Downloads
Patches
Plain Diff
Operationen auf Binärbäumen in rekursiver Formulierung
parent
49ffbcc8
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
303_Binaerbaeume.tex
+146
-0
146 additions, 0 deletions
303_Binaerbaeume.tex
bilder/BST_delete.tex
+68
-0
68 additions, 0 deletions
bilder/BST_delete.tex
with
214 additions
and
0 deletions
303_Binaerbaeume.tex
+
146
−
0
View file @
ce29f15c
...
@@ -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.
...
...
This diff is collapsed.
Click to expand it.
bilder/BST_delete.tex
0 → 100644
+
68
−
0
View file @
ce29f15c
\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}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment