1
0
mirror of https://github.com/2martens/uni.git synced 2026-05-06 11:26:25 +02:00

15 Commits

5 changed files with 127 additions and 42 deletions

1
.gitignore vendored
View File

@ -33,3 +33,4 @@
*.xdy
*.tdo
*.zip
*~

View File

@ -5,12 +5,15 @@
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{bytefield}
\usepackage{paralist}
\usepackage{gauss}
\usepackage{pgfplots}
\usepackage{textcomp}
\usepackage[locale=DE,exponent-product=\cdot,detect-all]{siunitx}
\usepackage{tikz}
\usepackage{algorithm}
\usepackage{algorithmic}
\usetikzlibrary{matrix,fadings,calc,positioning,decorations.pathreplacing,arrows,decorations.markings}
\usepackage{polynom}
\polyset{style=C, div=:,vars=x}
@ -25,9 +28,12 @@
\let\@ifnextchar\new@ifnextchar
\array{#1}}
\makeatother
\parskip 12pt plus 1pt minus 1pt
\parindent 0pt
\begin{document}
\author{Tronje Krabbe, Jim Martens (6420323)}
\author{Reinhard Köhler (6425886?), Tronje Krabbe (6435002), \\
Jim Martens (6420323)}
\title{Hausaufgaben zum 6. November}
\subtitle{Gruppe 8}
\maketitle
@ -37,22 +43,53 @@
\subsection{} %b
Ein voller Baum der Tiefe $l$ hat auf der untersten Ebene $k^{l}$ Knoten. Daraus ergibt sich diese Summe:
\[
\sum\limits_{i=0}^{l} k^{i}
\sum\limits_{i=0}^{l} k^{i} = k^{l+1} - 1
\]
Dies gilt da in einem vollen Baum die Anzahl Knoten in einer Ebene immer einer Potenz von $k$ entsprechen.
\subsection{} %c
Ein vollständiger Baum der Tiefe $l$ gleicht bis auf die letzte Ebene einem vollen Baum. In der letzten Ebene $l$ kommen maximal $k^{l} - 1$ Knoten vor, damit es ein vollständiger Baum, aber kein voller Baum ist. Daraus ergibt sich diese leicht abgewandelte Formel:
\[
\sum\limits_{i=0}^{l-1} \left(k^{i}\right) + c : 1 \leq c < k^{l}
\]
\begin{alignat*}{2}
\sum\limits_{i=0}^{l-1} \left(k^{i}\right) + c &:& 1 \leq c < k^{l}
\end{alignat*}
\subsection{} %d
Jeder Knoten hat genau ein Elternknoten mit dem er über eine Kante verbunden ist. Einzige Ausnahme ist der Wurzelknoten, der kein Elternelement hat und damit auch keine Kante, die mit einem solchen verbunden sein könnte. Daher gibt es genau $n-1$ Kanten.
\section{} %2
\subsection{} %a
Laufzeit von Order1:
\[
T(n) = 2T\left(\frac{n}{2}\right) + n^{0}
\]
Laufzeit von Order2:
\[
T(n) = 2T\left(\frac{n}{2}\right) + n^{0}
\]
Laufzeit von Order3:
\[
T(n) = 2T\left(\frac{n}{2}\right) + n^{0}
\]
\subsection{} %b
Die Laufzeiten von Order1, Order2 und Order3 können im best-case auf $1$ verbessert werden.
\subsection{} %c
Order1: NAOEIFMRLUSGARTH \\
Order2: IEOFARMLNGSAUTRH \\
Order3: IEFORLMAGASTHRUN
\subsection{} %d
T = \begin{bytefield}{10}
\bitbox{1}{T}
\bitbox{1}{E}
\bitbox{1}{E}
\bitbox{1}{O}
\bitbox{1}{Y}
\bitbox{1}{R}
\bitbox{1}{E}
\bitbox{1}{L}
\bitbox{1}{V}
\bitbox{1}{L}
\end{bytefield}
\subsection{} %e
ALGORITHMSAREFUN
\section{} %3
\subsection{} %a
\begin{alignat*}{2}
@ -71,10 +108,31 @@
\end{alignat*}
Das Ergebnis der letzten Gleichung ist somit das Minima von $f$. Als weitere Absicherung kann das asymptotische Wachstum betrachtet werden. Für einen kleineren Wert als $e$, ist $\ln(x)$ kleiner als $1$. Das Teilen von $x$ durch diesen Wert geringer als $1$ sorgt dafür, dass das Ergebnis größer als $x$ ist. Lässt man $x$ gegen $1$ laufen, läuft der Bruch gegen unendlich. Auf der anderen Seite kann man $x$ gegen unendlich gehen lassen, dann läuft der Bruch auch gegen unendlich, da eine lineare Funktion schneller wächst, als eine logarithmische. Der konstante Faktor am Ende kann dabei außer Acht gelassen werden.
\subsection{} %b
Die beste Wahl für $k^{*}$ ist $3$. Es werden im worst-case bei der Heap-Größe $n=10^{l}$ mit $l \in \{1,...,9\}$ diese Anzahl an Schritten benötigt.
\begin{tabular}{c|c|c}
$l$ & $k = 3$ & $k = 2$ \\
\hline
1 & 7 & 7 \\
2 & 13 & 14 \\
3 & 19 & 20 \\
4 & 26 & 27 \\
5 & 32 & 34 \\
6 & 38 & 40 \\
7 & 45 & 47 \\
8 & 51 & 54 \\
9 & 57 & 60
\end{tabular}
\subsection{} %c
Ein binärer Heap (dementsprechend $k=2$) ist deutlich übersichtlicher als ein ternärer Heap. Außerdem ist ein binärer Heap leichter zu be- bzw. verarbeiten und der Unterschied des Laufzeitaufwandes zwischen einem binären und einem ternären Heap ist nicht sonderlich groß.
\subsection{} %d
Pro Vertauschen werden $k+1$ Schritte benötigt. Ein Schritt wird benötigt, um das Maximum herauszufinden und $k$ Schritte, um den Max-Heap des aktuellen Knoten nach dem Vertauschen wieder zu einem solchen zu machen. Damit werden zwar viele Schritte zum Finden eines Maximums der Kinder eingespart, allerdings an anderer Stelle wieder durch das Aufrufen von Heapify auf den zusätzlichen Max-Heap ausgegeben. Im Endeffekt ergibt sich damit eine Gesamtlaufzeit von $\lceil (k+1)\log_{k}(n) \rceil$.
\subsection{} %e
Anwenden von \textsc{Decrease}$(9 \mapsto 1)$ auf Ergebnis von 3d: 2 Vertauschungen \\
Anwenden von \textsc{Decrease}$(9 \mapsto 1)$ auf Ergebnis von 3f: eine Vertauschung
\subsection{} %f
Ein ternärer Heap hat bei gleicher Anzahl an Knoten maximal gleich viele Level, wodurch dieselbe \textsc{Decrease}-Operation bei einem ternären Heap immer maximal gleich viele Vertauschungen wie bei einem binären Heap erfordert.
\section{} %4
\subsection{} %a
merge (2 2 5 7 9, 1 2 4 8) \\
@ -86,7 +144,7 @@
1 2 2 2 4 5 $\circ$ merge (7 9, 8) \\
1 2 2 2 4 5 7 $\circ$ merge (9, 8) \\
1 2 2 2 4 5 7 8 $\circ$ merge (9, []) \\
1 2 2 2 4 5 7 8 9
1 2 2 2 4 5 7 8 9
\subsection{} %b
Input 6 7 8 3 4 2 9 1 \\
Rekursiv in einzelne Ziffern zerlegt und dann zusammengefügt: \\
@ -116,27 +174,53 @@
\draw [brace] (a3.south) -- (a4.south);
\draw [brace] (a5.south) -- (a6.south);
\draw [brace] (a7.south) -- (a8.south);
\node [position label] (b1) at (0.25,-0.7) {$67$};
\node [position label] (b2) at (1.25,-0.7) {$38$};
\node [position label] (b3) at (2.25,-0.7) {$24$};
\node [position label] (b4) at (3.25,-0.7) {$19$};
\draw [brace,decoration={raise=4ex}] (a1.south) -- (a4.south);
\draw [brace,decoration={raise=4ex}] (a5.south) -- (a8.south);
\node [position label] (c1) at (0.75,-1.4) {$3678$};
\node [position label] (c2) at (2.75,-1.4) {$1249$};
\draw [brace,decoration={raise=8ex}] (a1.south) -- (a8.south);
\draw [brace,decoration={raise=8ex}] (a1.south) -- (a8.south);
\node [position label] (d1) at (1.75,-2.1) {$12346789$};
\end{tikzpicture}
\subsection{} %c
Eine Möglichkeit eine absteigende Sortierung zu erreichen, ist das Umkehren von $x[1] \leq y[1]$ zu $x[1] \geq y[1]$.
Eine andere Möglichkeit ist das Vertauschen der Fälle in der \texttt{if}-Abfrage. Dabei bleibt die Bedingung der Abfrage gleich, allerdings wird statt dem ersten Element von $x$ das erste Element von $y$ genommen. Im \texttt{else}-Fall wird dann dementsprechend das erste Element von $x$ genommen.
\section{} %5
\subsection{} %a
Man benutzt einen Stack als Zwischenspeicher und einen Stack als die eigentliche Queue. Soll ein Element in die Queue eingefügt werden, wird jedes Element des Hauptstacks nach und nach entfernt und auf den Speicherstack geschrieben. Dann wird das hinzuzufügende Element in den Hauptstack geschrieben. Danach werden nach und nach alle Elemente aus dem Speicherstack entfernt und auf den Hauptstack geschrieben. So sind in dem Hauptstack die Elemente in der Reihenfolge gespeichert, in der sie ausgelesen werden sollen (FIFO-Prinzip). Soll nun ein Element aus der Queue entfernt werden, wird einfach die pop-Operation an dem Hauptstack aufgerufen, womit das Element, das zuerst eingefügt wurde, entfernt wird, wie es bei einer Queue der Fall ist.
\begin{verbatim}
function ENQUEUE(e):
if Hauptstack.isEmpty():
Hauptstack.push(e);
else:
for element in Hauptstack:
Speicherstack.push(element);
Hauptstack.pop();
end for
Hauptstack.push(e);
for element in Speicherstack:
Hauptstack.push(element);
Speicherstack.pop();
end for
end if
end function
function DEQUEUE():
Hauptstack.pop();
end function
\end{verbatim}
Im worst-case ist die Laufzeit von \textsc{Dequeue} $\theta(1)$. Die worst-case Laufzeit von \textsc{Enqueue} ist bei $k$ Elementen $2k+1$.
\subsection{} %b
Die worst-case Laufzeit von $n$ \textsc{Enqueue}-Operationen beträgt $n \cdot (2n+1) = 2n^{2} + n$. Die amortisierte Laufzeit beträgt dann $\frac{n(2n+1)}{n} = 2n+1$. Dabei muss beachtet werden, dass bei weniger \textsc{Enqueue}- und mehr \textsc{Dequeue}-Operationen dementsprechend auch das Ergebnis weniger groß ausfällt.
\end{document}

View File

@ -34,29 +34,29 @@
\section{} %1
\subsection{} %a
$\frac{1}{n} \prec 1$, da man immer eine Konstante $c$ finden kann, für die ab einem $n$ alle weiteren Funktionswerte von $\frac{1}{n}$ unter $c \cdot \mathcal{O}(1)$ liegen.
$1 \prec \log\log n$, da der Logarithmus schneller wächst als eine konstante Funktion und jeder Logarithmus langsamer wächst als eine polynomielle Funktion. Der doppelte Logarithmus wächst noch langsamer als der einfache Logarithmus.
$\log\log n \prec \log n$, da der einfache Logarithmus schneller wächst als der doppelte Logarithmus.
$\log n \asymp \log(n^{3})$, da sich die beiden nur um einen konstanten Faktor $3$ unterscheiden.
$\log(n^{3}) \prec \log(n^{\log n})$, da $\frac{\log n \cdot \log n}{3 \cdot \log n}$ gegen unendlich geht.
$\log(n^{\log n}) \prec n^{0.01}$, da jeder Logarithmus langsamer wächst als eine polynomielle Funktion.
$n^{0.01} \prec \sqrt{n}$, da $\frac{n^{0.5}}{n^{0.01}}$ nach dem Kürzen gegen unendlich geht.
$\sqrt{n} \prec n \cdot \log n$, da $\frac{n \cdot \log n}{n^{0.5}}$ nach dem Kürzen gegen unendlich geht.
$n \cdot \log n \prec n^{8}$, da $\frac{n^{8}}{n \cdot \log n}$ nach dem Kürzen gegen unendlich geht, weil jeder Logarithmus langsamer wächst als jede polynomielle Funktion.
$n^{8} \prec 2^{n}$, da jede Exponentialfunktion schneller wächst als jede polynomielle Funktion.
$2^{n} \prec 8^{n}$, da $8 > 2$, womit $8^{n}$ klar ersichtlich schneller wächst als $2^{n}$.
$8^{n} \prec n!$, da $\frac{n \cdot (n-1) \cdot ... \cdot 3 \cdot 2 \cdot 1}{8 \cdot 8 \cdot ... \cdot 8 \cdot 8 \cdot 8}$ ganz offensichtlich gegen unendlich geht.
$n! \prec n^{n}$, da $\frac{n \cdot n \cdot n \cdot ... \cdot n \cdot n}{n \cdot (n-1) \cdot (n-2) \cdot ... \cdot 2 \cdot 1}$ ebenfalls gegen unendlich geht.
\subsection{} %b
\subsubsection{} %i
@ -65,8 +65,8 @@
\subsubsection{} %ii
Behauptung: $f \in \mathcal{O}(g) \Rightarrow g \in \omega (f)$\\
Diese Behauptung gilt nicht. Dies kann mithilfe der Definition der Landau-Symbole erklärt werden. $f \in \mathcal{O}(g)$ besagt, dass $f$ maximal so schnell wie $g$ wächst. Dabei ist auch der Fall enthalten, dass $f$ und $g$ gleich schnell wachsen.
Der zweite Teil der Behauptung erfordert jedoch, dass $g$ in jedem Fall schneller als $f$ wächst. Dies steht aber im Widerspruch zu dem ersten Teil der Behauptung. Damit ist die Behauptung widerlegt.
Der zweite Teil der Behauptung erfordert jedoch, dass $g$ in jedem Fall schneller als $f$ wächst. Dies steht aber im Widerspruch zu dem ersten Teil der Behauptung. Damit ist die Behauptung widerlegt.
\subsubsection{} %iii
Behauptung: $f_{c}(n) \in \theta(n) \Leftrightarrow c = 1$.\\
Dies ist einfach zu zeigen:\\
@ -74,7 +74,7 @@
\sum\limits_{i=0}^{n} 1^{i} &=& 1 + 1 + 1 + ... + 1 = n + 1
\end{alignat*}
Denn für $c=1$ werden einfach $n+1$ Einsen aufsummiert. Die Summe $n+1$ wächst asymptotisch genau so schnell wie $n$, da die Konstante $1$ vernachlässigt werden kann.
\section{} %2
\subsection{} %a
\underline{Behauptung:} $F_{n} \geq 2^{0.5n} : \forall n \geq 6$\\
@ -103,7 +103,7 @@
\end{alignat*}
Damit ist die Behauptung sowohl für den Induktionsanfang als auch für ein beliebiges $n$ gezeigt.
\subsection{} %b
\section{} %3
\subsection{} %a
\underline{Behauptung:} Die Formel
@ -117,7 +117,7 @@
\end{pmatrix}^{n} \cdot \begin{pmatrix}
F_{0} \\
F_{1}
\end{pmatrix}
\end{pmatrix}
\end{alignat*}
gilt für $n \geq 0$.\\
\underline{Induktionsanfang:}\\
@ -145,7 +145,7 @@
\end{pmatrix}
\end{alignat*}\\
\underline{Induktionsannahme:} Die Behauptung gilt für ein beliebig fest gewähltes $n$.\\
\underline{Zu zeigen:}
\underline{Zu zeigen:}
\begin{alignat*}{2}
\begin{pmatrix}
F_{n+1} \\
@ -156,7 +156,7 @@
\end{pmatrix}^{n+1} \cdot \begin{pmatrix}
F_{0} \\
F_{1}
\end{pmatrix}
\end{pmatrix}
\end{alignat*}
\underline{Induktionsschritt:}
\begin{alignat*}{2}
@ -189,7 +189,7 @@
F_{1}
\end{pmatrix}
\end{alignat*}
Nach dem Induktionsprinzip folgt aus dem Induktionsanfang und dem Induktionsschritt die Behauptung.
Nach dem Induktionsprinzip folgt aus dem Induktionsanfang und dem Induktionsschritt die Behauptung.
\subsection{} %b
$X^{64}$ kann geschickter berechnet werden, wenn man die Ergebnisse von vorigen Multiplikationen speichert. Damit lässt sich $X^{64}$ auf diese Weise berechnen:\\
\begin{alignat*}{3}
@ -206,7 +206,7 @@
& X^{72} &\cdot & X^{2} &=& X^{74}
\end{alignat*}
Demnach würden bei $74$ acht Multiplikationen benötigt.
Daraus kann die allgemeine Formel für die Anzahl der Multiplikationen $F(n)$ gebildet werden:\\
\begin{alignat*}{2}
F(n) &=& \begin{cases}
@ -215,9 +215,9 @@
\end{cases}
\end{alignat*}
Diese rekursive Formel könnte auch als Schleife dargestellt werden. Durch die Halbierung von n bei jedem Durchgang hat die Funktion eine logarithmische Laufzeit. Die Addition ist dabei irrelevant, wenn man sich das asymptotische Verhalten ansieht.
Damit ist die Behauptung, dass $\mathcal{O}(\log n)$ Multiplikationen ausreichen um $X^{n}$ zu berechnen, gezeigt.
\subsection{} %c
In 3b haben wir gezeigt, dass sich $X^{n}$ in $\mathcal{O}(\log n)$ Multiplikationen ausgerechnen lässt. Daraus lässt sich schließen, dass sich auch die 2x2 Matrix in $\star$ in logarithmischer Zeit errechnen lässt. Eine weitere Multiplikation macht dann auch keinen Unterschied mehr. Daher lässt sich $\star$ in logarithmischer Zeit lösen. Da jeder Logarithmus langsamer wächst und damit schneller ist als eine Potenzfunktion, ist das Matrizen-Verfahren damit echt schneller als das in der Vorlesung vorgestellte Verfahren.
\end{document}

View File

@ -149,10 +149,10 @@ Stephan Niendorf (6242417)}
(x_{1}, x_{2}) &=& \left(\frac{1}{3} + \frac{1}{3}t, \frac{7}{3} + \frac{4}{3}t\right) \\
&=& \left(\frac{1}{3}, \frac{7}{3}\right) + t\left(\frac{1}{3}, \frac{4}{3}\right)
\end{alignat*}
\begin{alignat*}{2}
(x_{3}, x_{2}) &=& \left(t, \frac{7}{3} + \frac{4}{3}t\right) \\
&=& \left(0, \frac{7}{3}\right) + t\left(1, \frac{4}{3}\right)
\end{alignat*}
%\begin{alignat*}{2}
% (x_{3}, x_{2}) &=& \left(t, \frac{7}{3} + \frac{4}{3}t\right) \\
% &=& \left(0, \frac{7}{3}\right) + t\left(1, \frac{4}{3}\right)
%\end{alignat*}
Da in diesem Fall $x_{1}$ eine Basisvariable ist und somit nicht gleich $t$ ist, stellt $t$ eine beliebige positive Konstante dar. Daher verändert sich auch die Gerade je nach Wahl von $t$. Deswegen ist es nicht möglich genau eine Halbgerade zu finden, auf der die Zielfunktion beliebig große Werte annimmt.
\subsection{} %b
@ -180,7 +180,7 @@ Stephan Niendorf (6242417)}
\addplot[no marks, black, -] expression[domain=0:6,samples=100]{4*x + 1} node[pos=0.65,anchor=north]{};
\addplot[no marks, black, -] expression[domain=0:6,samples=100]{1*x + 2} node[pos=0.65,anchor=north]{};
\addplot[no marks, black, -] expression[domain=0:6,samples=100]{0.5*x - 1} node[pos=0.65,anchor=north]{};
\addplot[no marks, black, -] expression[domain=0:6,samples=100]{1.333333333333333*x + 2.33333333333333333} node[pos=0.65,anchor=north]{};
%\addplot[no marks, black, -] expression[domain=0:6,samples=100]{1.333333333333333*x + 2.33333333333333333} node[pos=0.65,anchor=north]{};
%\node at (axis cs: 2.5,4.5) {(2.25,3.75)};
%\node at (axis cs: 6,2) {z};
%\draw[>=stealth] (axis cs:1,0) -- (axis cs:1,-6) node [pos=0.65,anchor=north]{};

View File

@ -2,7 +2,7 @@
#|
SE 3 Funktional Blatt 1
Abgebende: Jim 2martens, 2noack, 0giebel
Abgebende: Jim 2martens, Britta 2noack, Jan-Simon 0giesel
|#
; 1.1