Programmiertechniken.tex 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. \chapter{Programmiertechniken}
  2. \section{Rekursion}
  3. \index{Rekursion|(}
  4. \begin{definition}[rekursive Funktion]\xindex{Funktion!rekursive}
  5. Eine Funktion $f: X \rightarrow X$ heißt rekursiv definiert,
  6. wenn in der Definition der Funktion die Funktion selbst wieder
  7. steht.
  8. \end{definition}
  9. \begin{beispiel}[rekursive Funktionen]
  10. \begin{bspenum}
  11. \item Fibonacci-Funktion:\xindex{Fibonacci-Funktion}
  12. \begin{align*}
  13. fib: \mdn_0 &\rightarrow \mdn_0\\
  14. fib(n) &= \begin{cases}
  15. n &\text{falls } n \leq 1\\
  16. fib(n-1) + fib(n-2) &\text{sonst}
  17. \end{cases}
  18. \end{align*}
  19. Erzeugt die Zahlen $0, 1, 1, 2, 3, 5, 8, 13, \dots$
  20. \item Fakultät:\xindex{Fakultät}
  21. \begin{align*}
  22. ! &: \mdn_0 \rightarrow \mdn_0\\
  23. n! &= \begin{cases}
  24. 1 &\text{falls } n \leq 1\\
  25. n\cdot (n-1)! &\text{sonst}
  26. \end{cases}
  27. \end{align*}
  28. \item \label{bsp:binomialkoeffizient} Binomialkoeffizient:\xindex{Binomialkoeffizient}
  29. \begin{align*}
  30. \binom{\cdot}{\cdot} &: \mdn_0 \times \mdn_0 \rightarrow \mdn_0\\
  31. \binom{n}{k} &= \begin{cases}
  32. 1 &\text{falls } k=0 \lor k = n\\
  33. \binom{n-1}{k-1}+\binom{n-1}{k} &\text{sonst}
  34. \end{cases}
  35. \end{align*}
  36. \end{bspenum}
  37. \end{beispiel}
  38. Ein Problem von rekursiven Funktionen in Computerprogrammen ist der
  39. Speicherbedarf. Für jeden rekursiven Aufruf müssen alle Umgebungsvariablen
  40. der aufrufenden Funktion (\enquote{stack frame}) gespeichert bleiben,
  41. bis der rekursive Aufruf beendet ist. Im Fall der Fibonacci-Funktion
  42. sieht ist der Call-Stack in \cref{fig:fib-callstack} abgebildet.
  43. \begin{figure}[htp]
  44. \centering
  45. \includegraphics*[width=0.5\linewidth, keepaspectratio]{figures/fib-callstack.png}
  46. \caption{Call-Stack der Fibonacci-Funktion}
  47. \label{fig:fib-callstack}
  48. \end{figure}
  49. \begin{bemerkung}
  50. Die Anzahl der rekursiven Aufrufe der Fibonacci-Funktion $f_C$ ist:
  51. \[f_C(n) = \begin{cases}
  52. 1 &\text{falls } n=0\\
  53. 2 \cdot fib(n) - 1 &\text{falls } n \geq 1
  54. \end{cases}\]
  55. \end{bemerkung}
  56. \begin{beweis}\leavevmode
  57. \begin{itemize}
  58. \item Offensichtlich gilt $f_C(0) = 1$
  59. \item Offensichtlich gilt $f_C(1) = 1 = 2 \cdot fib(1) - 1$
  60. \item Offensichtlich gilt $f_C(2) = 3 = 2 \cdot fib(2) - 1$
  61. \item Für $n \geq 3$:
  62. \begin{align*}
  63. f_C(n) &= 1 + f_C(n-1) + f_C(n-2)\\
  64. &= 1 + (2\cdot fib(n-1)-1) + (2 \cdot fib(n-2)-1)\\
  65. &=2\cdot (fib(n-1) + fib(n-2)) - 1\\
  66. &=2 \cdot fib(n) - 1
  67. \end{align*}
  68. \end{itemize}
  69. \end{beweis}
  70. Mit Hilfe der Formel von Moivre-Binet folgt:
  71. \[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\]
  72. Dabei ist der Speicherbedarf $\mathcal{O}(n)$. Dieser kann durch
  73. das Benutzen eines Akkumulators signifikant reduziert werden.\todo{TODO}
  74. \begin{definition}[linear rekursive Funktion]\xindex{Funktion!linear rekursive}%
  75. Eine Funktion heißt linear rekursiv, wenn in jedem Definitionszweig
  76. der Funktion höchstens ein rekursiver Aufruf vorkommt.
  77. \end{definition}
  78. \begin{definition}[endrekursive Funktion]\xindex{Funktion!endrekursive}\xindex{tail recursive}%
  79. Eine Funktion heißt endrekursiv, wenn in jedem Definitionszweig
  80. der Rekursive aufruf am Ende des Ausdrucks steht. Der rekursive
  81. Aufruf darf also insbesondere nicht in einen anderen Ausdruck
  82. eingebettet sein.
  83. \end{definition}
  84. Auf Englisch heißen endrekursive Funktionen \textit{tail recursive}.
  85. \begin{beispiel}[Linear- und endrekursive Funktionen]
  86. \begin{bspenum}
  87. \item \texttt{fak n = if (n==0) then 1 else (n * fak (n-1))}\\
  88. ist eine linear rekursive Funkion, aber nicht endrekursiv,
  89. da nach der Rückgabe von \texttt{fak (n-1)} noch die Multiplikation
  90. ausgewertet werden muss.
  91. \item \texttt{fakAcc n acc = if (n==0) then acc else fakAcc (n-1) (n*acc)}\\
  92. ist eine endrekursive Funktion.
  93. \item \texttt{fib n = n <= 1 ? n : fib(n-1) + fib (n-2)}\\
  94. ist weder linear- noch endrekursiv.
  95. \end{bspenum}
  96. \end{beispiel}
  97. \index{Rekursion|)}
  98. \section{Backtracking}
  99. \index{Backtracking|(}
  100. \index{Backtracking|)}
  101. \section{Funktionen höherer Ordnung}
  102. Funktionen höherer Ordnung sind Funktionen, die auf Funktionen arbeiten.
  103. Bekannte Beispiele sind:
  104. \begin{itemize}
  105. \item \texttt{map(function, list)}\xindex{map}\\
  106. \texttt{map} wendet \texttt{function} auf jedes einzelne
  107. Element aus \texttt{list} an.
  108. \item \texttt{filter(function, list)}\xindex{filter}\\
  109. \texttt{filter} gibt eine Liste aus Elementen zurück, für
  110. die \texttt{function} mit \texttt{true} evaluiert.
  111. \item \texttt{reduce(function, list)}\xindex{reduce}\\
  112. \texttt{function} ist für zwei Elemente aus \texttt{list}
  113. definiert und gibt ein Element des gleichen Typs zurück.
  114. Nun steckt \texttt{reduce} zuerst zwei Elemente aus \texttt{list}
  115. in \texttt{function}, merkt sich dann das Ergebnis und nimmt
  116. so lange weitere Elemente aus \texttt{list}, bis jedes
  117. Element genommen wurde.
  118. \end{itemize}