2
0
Fork 0
mirror of https://github.com/MartinThoma/LaTeX-examples.git synced 2025-04-25 06:18:05 +02:00

Abschnitt über Rekursion hinzugefügt

This commit is contained in:
Martin Thoma 2014-02-02 17:48:55 +01:00
parent 156a09095a
commit 7e99fea83a
7 changed files with 115 additions and 8 deletions

View file

@ -7,3 +7,4 @@ in dem Erstellen dieses Skripts steckt:
|01.02.2014 | 14:00 - 14:45 | Thoma | ASCII-Tabelle in C angefangen; Kapitel "Programmiersprachen" hinzugefügt; erste Definitionen |01.02.2014 | 14:00 - 14:45 | Thoma | ASCII-Tabelle in C angefangen; Kapitel "Programmiersprachen" hinzugefügt; erste Definitionen
|01.02.2014 | 14:45 - 15:30 | Thoma | Haskell angefangen |01.02.2014 | 14:45 - 15:30 | Thoma | Haskell angefangen
|01.02.2014 | 11:15 - 11:45 | Thoma | Haskell Class Hierachy |01.02.2014 | 11:15 - 11:45 | Thoma | Haskell Class Hierachy
|01.02.2014 | 16:00 - 17:00 | Thoma | Abschnitt über Rekursion hinzugefügt

View file

@ -40,12 +40,7 @@ definiert:
\inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/einfaches-beispiel-klammern.hs} \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/einfaches-beispiel-klammern.hs}
\subsection{if / else} \subsection{if / else}
Das folgende Beispiel definiert den Binomialkoeffizienten Das folgende Beispiel definiert den Binomialkoeffizienten (vgl. \cref{bsp:binomialkoeffizient})
\[\binom{n}{k} := \begin{cases}
1 &\text{falls } k=0 \lor k = n\\
\binom{n-1}{k-1}+\binom{n-1}{k} &\text{sonst}
\end{cases}\]
für $n,k \geq 0$:
\inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/binomialkoeffizient.hs} \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/binomialkoeffizient.hs}
\inputminted[numbersep=5pt, tabsize=4]{bash}{scripts/haskell/compile-binom.sh} \inputminted[numbersep=5pt, tabsize=4]{bash}{scripts/haskell/compile-binom.sh}
@ -65,6 +60,9 @@ hat einen Speicherverbrauch von $\mathcal{O}(n)$. Durch einen
\textbf{Akkumulator}\xindex{Akkumulator} kann dies verhindert werden: \textbf{Akkumulator}\xindex{Akkumulator} kann dies verhindert werden:
\inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/fakultaet-akkumulator.hs} \inputminted[numbersep=5pt, tabsize=4]{haskell}{scripts/haskell/fakultaet-akkumulator.hs}
\subsection{Listen}
\todo[inline]{Cons-Operator, Unendliche Listen}
\section{Beispiele} \section{Beispiele}
\subsection{Hello World} \subsection{Hello World}
Speichere folgenden Quelltext als \texttt{hello-world.hs}: Speichere folgenden Quelltext als \texttt{hello-world.hs}:

View file

@ -1,5 +1,98 @@
\chapter{Programmiertechniken} \chapter{Programmiertechniken}
\section{Rekursion} \section{Rekursion}
\todo[inline]{Tail-Recursion} \index{Rekursion|(}
\begin{definition}[rekursive Funktion]\xindex{Funktion!rekursive}
Eine Funktion $f: X \rightarrow X$ heißt rekursiv definiert,
wenn in der Definition der Funktion die Funktion selbst wieder
steht.
\end{definition}
\begin{beispiel}[rekursive Funktionen]
\begin{bspenum}
\item Fibonacci-Funktion:\xindex{Fibonacci-Funktion}
\begin{align*}
fib: \mdn_0 &\rightarrow \mdn_0\\
fib(n) &= \begin{cases}
n &\text{falls } n \leq 1\\
fib(n-1) + fib(n-2) &\text{sonst}
\end{cases}
\end{align*}
\item Fakultät:\xindex{Fakultät}
\begin{align*}
!: \mdn_0 &\rightarrow \mdn_0\\
n! &= \begin{cases}
1 &\text{falls } n \leq 1\\
n\cdot (n-1)! &\text{sonst}
\end{cases}
\end{align*}
\item \label{bsp:binomialkoeffizient} Binomialkoeffizient:\xindex{Binomialkoeffizient}
\begin{align*}
\binom{\cdot}{\cdot}: \mdn_0 \times \mdn_0 &\rightarrow \mdn_0\\
\binom{n}{k} &= \begin{cases}
1 &\text{falls } k=0 \lor k = n\\
\binom{n-1}{k-1}+\binom{n-1}{k} &\text{sonst}
\end{cases}
\end{align*}
\end{bspenum}
\end{beispiel}
Ein Problem von rekursiven Funktionen in Computerprogrammen ist der
Speicherbedarf. Für jeden rekursiven Aufruf müssen alle Umgebungsvariablen
der aufrufenden Funktion (\enquote{stack frame}) gespeichert bleiben,
bis der rekursive Aufruf beendet ist. Im Fall der Fibonacci-Funktion
sieht ist der Call-Stack in \cref{fig:fib-callstack} abgebildet.
\begin{figure}[htp]
\centering
\includegraphics*[width=0.5\linewidth, keepaspectratio]{figures/fib-callstack.png}
\caption{Call-Stack der Fibonacci-Funktion}
\label{fig:fib-callstack}
\end{figure}
\begin{bemerkung}
Die Anzahl der rekursiven Aufrufe der Fibonacci-Funktion $f_C$ ist:
\[f_C(n) = \begin{cases}
1 &\text{falls } n=0\\
2 \cdot fib(n) - 1 &\text{falls } n \geq 1
\end{cases}\]
\end{bemerkung}
\begin{beweis}\leavevmode
\begin{itemize}
\item Offensichtlich gilt $f_C(0) = 1$
\item Offensichtlich gilt $f_C(1) = 1 = 2 \cdot fib(1) - 1$
\item Offensichtlich gilt $f_C(2) = 3 = 2 \cdot fib(2) - 1$
\item Für $n \geq 3$:
\begin{align*}
f_C(n) &= 1 + f_C(n-1) + f_C(n-2)\\
&= 1 + (2\cdot fib(n-1)-1) + (2 \cdot fib(n-2)-1)\\
&=2\cdot (fib(n-1) + fib(n-2)) - 1\\
&=2 \cdot fib(n) - 1
\end{align*}
\end{itemize}
\end{beweis}
Mit Hilfe der Formel von Moivre-Binet folgt:
\[f_C \in \mathcal{O} \left (\frac{\varphi^n- \psi^n}{\varphi - \psi} \right) \text{ mit } \varphi := \frac{1+ \sqrt{5}}{2} \text{ und }\psi := 1 - \varphi\]
Dabei ist der Speicherbedarf $\mathcal{O}(n)$. Dieser kann durch
das Benutzen eines Akkumulators signifikant reduziert werden.\todo{TODO}
\begin{definition}[linear rekursive Funktion]\xindex{Funktion!linear rekursive}
Eine Funktion heißt linear rekursiv, wenn in jedem Definitionszweig
der Funktion höchstens ein rekursiver Aufruf vorkommt.
\end{definition}
\begin{definition}[endrekursive Funktion]\xindex{Funktion!endrekursive}\xindex{tail recursive}
Eine Funktion heißt endrekursiv, wenn in jedem Definitionszweig
der Rekursive aufruf am Ende des Ausdrucks steht. Der rekursive
Aufruf darf also insbesondere nicht in einen anderen Ausdruck
eingebettet sein.
\end{definition}
\todo[inline]{Beispiele für linear rekusrive, endrekursive Funktionen (alle Kombinationen+gegenbeispiele}
\index{Rekursion|(}
\section{Backtracking} \section{Backtracking}

View file

@ -24,7 +24,8 @@ TODO
\section*{Erforderliche Vorkenntnisse} \section*{Erforderliche Vorkenntnisse}
Grundlegende Kenntnisse vom Programmieren, insbesondere mit Java, Grundlegende Kenntnisse vom Programmieren, insbesondere mit Java,
wie sie am KIT in \enquote{Programmieren} vermittelt werden, werden wie sie am KIT in \enquote{Programmieren} vermittelt werden, werden
vorausgesetzt. vorausgesetzt. Außerdem könnte ein grundlegendes Verständnis für
das O-Kalkül aus \enquote{Grundbegriffe der Informatik} hilfreich sein.
Die Unifikation wird wohl auch in \enquote{Formale Systeme} Die Unifikation wird wohl auch in \enquote{Formale Systeme}
erklärt; das könnte also hier von Vorteil sein. erklärt; das könnte also hier von Vorteil sein.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -0,0 +1,14 @@
fib(3)
├ call(fib(2))
│ ├─ call(fib(1))
│ │ └─ return 1
│ ├─ call(fib(0))
│ │ └─ return 1
│ └ return fib(1)+fib(0)=1+1
├ call(fib(1))
│ ├─ call(fib(1))
│ │ └─ return 1
│ ├─ call(fib(0))
│ │ └─ return 1
│ └ return fib(1)+fib(0)=1+1
└ return fib(2)+fib(1)=2+2