mirror of https://github.com/2martens/uni.git
148 lines
6.8 KiB
TeX
148 lines
6.8 KiB
TeX
\documentclass[10pt,a4paper,oneside,ngerman,numbers=noenddot]{scrartcl}
|
|
\usepackage[T1]{fontenc}
|
|
\usepackage[utf8]{inputenc}
|
|
\usepackage[ngerman]{babel}
|
|
\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{automata,matrix,fadings,calc,positioning,decorations.pathreplacing,arrows,decorations.markings}
|
|
\usepackage{polynom}
|
|
\polyset{style=C, div=:,vars=x}
|
|
\pgfplotsset{compat=1.8}
|
|
\pagenumbering{arabic}
|
|
\def\thesection{\arabic{section})}
|
|
\def\thesubsection{(\alph{subsection})}
|
|
\def\thesubsubsection{(\roman{subsubsection})}
|
|
\makeatletter
|
|
\renewcommand*\env@matrix[1][*\c@MaxMatrixCols c]{%
|
|
\hskip -\arraycolsep
|
|
\let\@ifnextchar\new@ifnextchar
|
|
\array{#1}}
|
|
\makeatother
|
|
\parskip 12pt plus 1pt minus 1pt
|
|
\parindent 0pt
|
|
|
|
\begin{document}
|
|
\author{Reinhard Köhler (6425686), Tronje Krabbe (6435002), \\
|
|
Jim Martens (6420323)}
|
|
\title{Hausaufgaben zum 4. Dezember}
|
|
\subtitle{Gruppe 8}
|
|
\maketitle
|
|
\section{} %1
|
|
\subsection{} %a
|
|
Der Algorithmus funktioniert nicht weiterhin. Dies wird anhand dieses Gegenbeispiels deutlich:
|
|
|
|
\begin{verbatim}
|
|
A = [0,1,4,8,10,13]
|
|
value = 1
|
|
low = 0
|
|
high = 5
|
|
// erster Schleifendurchlauf 0 < 5, daher Rumpf ausführen
|
|
mid = (0 + 5) / 2 = 2
|
|
// A[2] = 4 > value
|
|
high = 2 - 1 = 1
|
|
// zweiter Schleifendurchlauf 0 < 1, daher Rumpf ausführen
|
|
mid = (0 + 1) / 2 = 0
|
|
// A[0] = 0 < value
|
|
low = 0 + 1 = 1
|
|
// dritter Schleifendurchlauf 1 = 1, daher Rumpf nicht ausführen
|
|
return not_found
|
|
\end{verbatim}
|
|
|
|
Obwohl das Element vorhanden ist, wird zurückgegeben, dass es nicht vorhanden sei. Da es ein Gegenbeispiel gibt, funktioniert der Algorithmus nach der Änderung von \texttt{while (low <= high)} zu \texttt{while (low < high)} nicht mehr.
|
|
\subsection{} %b
|
|
\begin{verbatim}
|
|
BinarySearch(A[0..N-1], value) {
|
|
low = N - 1
|
|
high = 0
|
|
while (high <= low) {
|
|
// invariants: value > A[i] for all i < low
|
|
value < A[i] for all i > high
|
|
mid = (low + high) / 2
|
|
if (A[mid] > value)
|
|
high = mid + 1
|
|
else if (A[mid] < value)
|
|
low = mid - 1
|
|
else
|
|
return mid
|
|
}
|
|
return not_found
|
|
}
|
|
\end{verbatim}
|
|
\subsection{} %c
|
|
\textbf{Formaler Beweis:} Wir müssen beweisen, dass die while-Schleife endet. Angenommen wir befinden uns in Iteration $i$ der while-Schleife.
|
|
\begin{itemize}
|
|
\item Zu Beginn der while-Schleife haben wir \texttt{high $\leq$ low} (andernfalls hätten wir die while-Schleife nicht betreten).
|
|
\item Nach dem Ausdruck \texttt{mid = (low + high) / 2} gilt \texttt{high $\leq$ mid $\leq$ low}.
|
|
\item Entweder die Schleife wird durch die Rückgabe von \texttt{mid} beendet, womit wir fertig wären.
|
|
\item Oder sie befindet sich in einer der ersten beiden Fälle des if-Statements. Entweder high wird um mindestens eins erhöht oder low wird um mindestens eins verkleinert, wodurch sich in jedem Schleifendurchlauf die Differenz von \texttt{low - high} um mindestens eins verringert.
|
|
\item Damit gilt \texttt{low - high < 0} nach maximal $n$ Iterationen der while-Schleife und die Schleife terminiert.
|
|
\end{itemize}
|
|
\subsection{} %d
|
|
\textbf{Beweis der Korrektheit:}
|
|
|
|
Offensichtlich gibt der Algorithmus ein korrektes Ergebnis zurück, wenn \texttt{mid} zurückgegeben wird, da dann \texttt{A[mid] $=$ value} gilt.
|
|
|
|
Zu zeigen: Wenn der Algorithmus \texttt{not\_found} zurückgibt, dann kommt \texttt{value} tatsächlich nicht in dem Array vor.
|
|
|
|
Wir werden dies nun durch die Gegenposition beweisen: Wir müssen zeigen, dass wenn \texttt{value} im Array vorkommt, der Algorithmus \texttt{mid} zurückgibt.
|
|
|
|
\textbf{Erster Schritt:} Es ist einfach zu sehen, dass die folgenden Invarianten immer gelten:
|
|
\begin{itemize}
|
|
\item \texttt{value > A[i] for all i < low (strict inequality!)}
|
|
\item \texttt{value < A[i] for all i > high (strict inequality!)}
|
|
\end{itemize}
|
|
|
|
\textbf{Zweiter Schritt:} Annahme, dass \texttt{value} im Array vorkommt.
|
|
\begin{itemize}
|
|
\item Bereits bekannt: Invarianten sind wahr. Das bedeutet zu keinem Zeitpunkt im Algorithmus kann sich das Element, das wir suchen, links von \texttt{high} oder rechts von \texttt{low} befinden.
|
|
\item Der einzige Weg, wie wir theoretisch das gesuchte Element "`verpassen"' könnten, wäre, dass \texttt{high = mid + 1} oder \texttt{low = mid - 1} zu der Situation führen, dass \texttt{high > low} gilt bevor wir das gesuchte Element gefunden haben (weil wir dann die Schleife verlassen).
|
|
\begin{itemize}
|
|
\item Durch die Konstruktion des Algorithmus haben wir immer \texttt{high $\leq$ mid $\leq$ low} nachdem \texttt{mid = (low + high) / 2} ausgeführt wurde.
|
|
\item Solange \texttt{low $\geq$ high + 2} gilt, haben wir immer \texttt{high < mid < low}.
|
|
In dieser Situation, \texttt{mid - 1 $\geq$ high} und \texttt{mid + 1 $\leq$ low}, haben wir immer noch \texttt{high $\leq$ low} nachdem entweder \texttt{high = mid + 1} oder \texttt{low = mid - 1} ausgeführt wurden, sodass die while-Schleife ein weiteres Mal betreten wird.
|
|
|
|
Es gibt zwei kritische Fälle, in denen wir die Schleife verlassen könnten:
|
|
\begin{itemize}
|
|
\item \texttt{low = high}. Aber dann gilt auch \texttt{mid = high}. Nach der Annahme, dass \texttt{value} im Array ist, muss \texttt{A[high] = value} gelten. Durch die Rückgabe von \texttt{mid} wird demnach genau der richtige Index zurückgegeben.
|
|
\item \texttt{low = high + 1}. In diesem Fall gilt \texttt{mid = high}. Nun gilt entweder \texttt{A[high] = A[mid] = value}, wodurch durch Rückgabe von \texttt{mid} das richtige Ergebnis zurückgegeben würde, oder es gilt \texttt{A[high] = A[mid] > value}, wodurch \texttt{high} um eins erhöht würde, was beim nächsten Schleifendurchlauf im Fall \texttt{low = high} enden würde. In dem Fall wird das korrekte Ergebnis zurückgegeben, wie bereits gezeigt wurde.
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\item Dies zeigt, dass wenn \texttt{value} im Array vorhanden ist, der Algorithmus immer damit endet \texttt{mid} zurückzugeben.
|
|
\end{itemize}
|
|
\section{} %2
|
|
\subsection{} %a
|
|
\subsubsection{} %i
|
|
\subsubsection{} %ii
|
|
\subsubsection{} %iii
|
|
\subsection{} %b
|
|
\subsubsection{} %i
|
|
\subsubsection{} %ii
|
|
\subsubsection{} %iii
|
|
\subsection{} %c
|
|
\subsubsection{} %i
|
|
\subsubsection{} %ii
|
|
\subsubsection{} %iii
|
|
\subsubsection{} %iv
|
|
\section{} %3
|
|
\subsection{} %a
|
|
\subsection{} %b
|
|
\subsection{} %c
|
|
\subsection{} %d
|
|
\subsection{} %e
|
|
\subsection{} %f
|
|
\section{} %4
|
|
\subsection{} %a
|
|
\subsection{} %b
|
|
\subsection{} %c
|
|
\end{document}
|