diff --git a/205_Eigenschaften_von_Sortieralgorithmen.tex b/205_Eigenschaften_von_Sortieralgorithmen.tex
index 0a408b3b73f45e98457164f6b41206866371a832..dbfe64b5bd33d4ffa557a5bfcc47a15361062bcc 100644
--- a/205_Eigenschaften_von_Sortieralgorithmen.tex
+++ b/205_Eigenschaften_von_Sortieralgorithmen.tex
@@ -6,7 +6,8 @@ Sortieralgorithmus anhand seines best/worst/average-case-Verhaltens zu beurteile
 
 \subsection{worst-case-optimal}
 Im Zusammenhang von vergleichsbasierten Sortieralgorithmen bedeutet die Eigenschaft worst-case-optimal, dass die
-Untergrenze von $Ω(n \log n)$ \emph{immer} eingehalten wird.
+Untergrenze von $Ω(n \log n)$ auch die asymptotische Obergrenze ist, also die worst-case-Laufzeit in i$Θ(n \log n)$ 
+liegt.
 
 \subsection{Stabilität}
 Ein Sortieralgorithmus ist stabil, wenn durch das Sortieren die Reihenfolge innerhalb bezüglich der Quasiordnung
@@ -35,7 +36,7 @@ sind. Insbesondere muss der best-case also in $\mathcal{O}(n)$ liegen. Diese Def
 Fehlstellungen präzisieren:
 
 \begin{definition}[Fehlstände und Fehlstandszahl]
-  Sei A eine geordnete Menge und sei $[a_1, \dots, a_n] \in A^n$ eine Folge von Elementen in A. Die Anzahl der
+  Sei $A$ eine geordnete Menge und sei $[a_1, \dots, a_n] \in A^n$ eine Folge von Elementen in $A$. Die Anzahl der
   Fehlstände bezüglich $a_i$ ist 
   \[
     f_i := |\{a_j : j > i, a_j < a_i \}|,
diff --git a/300_Datenstrukturen.tex b/300_Datenstrukturen.tex
index 5aeb4afe4306cdf3feacc5ca770e83f149327db6..dccd330f2147c3c247eeb1ed771b509f5bd94521 100644
--- a/300_Datenstrukturen.tex
+++ b/300_Datenstrukturen.tex
@@ -2,6 +2,6 @@
 
 \input{301_dynamische_Arrays}
 \include{302_Hashtabellen}
-%\include{303_Binaerbaeume}
-%\include{304_Halden}
+\include{303_Binaerbaeume}
+\include{304_Halden}
 %\include{305_2-4-Baeume}
diff --git a/301_dynamische_Arrays.tex b/301_dynamische_Arrays.tex
index 99e458aabb4cbfa21bf41789b489f4f57fc5fdfc..c82fbb77a371b9213bc669678ada56098a36fd63 100644
--- a/301_dynamische_Arrays.tex
+++ b/301_dynamische_Arrays.tex
@@ -251,7 +251,7 @@ Damit können wir zeigen, dass das dynamische Array einen amortisierten Aufwand
 \end{theorem}
 \begin{proof}
   Sollten keinerlei Umstrukturierungen nötig sein, ist $a_i < e_i$ klar. Aber auch bei Umstrukturierungen ist aus dem
-  vorherigen Lemma klar: Ist $K_0 = 0$ und damit nicht negativ, bleibt $K_i \leq 0$ für alle $i \in \mathbb{N}$.
+  vorherigen Lemma klar: Ist $K_0 = 0$ und damit nicht negativ, bleibt $K_i ≥ 0$ für alle $i \in \mathbb{N}$.
   Da die tatsächliche Laufzeit $T(f_i) = a_i$, haben wir also 
   \[
     \sum_{i=1}^n T(f_i) = \sum_{i=1}^n a_i \leq \sum_{i=1}^n e_i \leq 3n.
diff --git a/303_Binaerbaeume.tex b/303_Binaerbaeume.tex
index 6fc1df17efd2865042e68373c8364f3eccc5b185..903a805ee28a8e0118251a27f3b272d139694af7 100644
--- a/303_Binaerbaeume.tex
+++ b/303_Binaerbaeume.tex
@@ -297,7 +297,7 @@ Soll der Knoten $k$ gelöscht werden, müssen drei Fälle unterschieden werden,
     die Referenz des Elternknotens von $k$ auf das Kind von $c$ um.
   \item Im letzten Fall hat $k$ hat zwei Kinder. Wir ersetzen die Daten von $k$ durch die Daten des nächstgrößeren
     Knotens $t$ und löschen dann den Knoten $t$. Da dieser nur maximal ein Kind hat (er kann kein linkes Kind haben,
-    sonst wäre dass das nächstgrößere) terminert dieser Rekursive Aufruf von $\texttt{delete}$ nach einem Schritt, da
+    sonst wäre dass das nächstgrößere) terminert dieser rekursive Aufruf von $\texttt{delete}$ nach einem Schritt, da
     wir einem der letzten beiden Fälle landen. Ist das Verschieben der Daten sehr teuer, so können wir alternativ auch
     alle Pointer so umbiegen, dass $t$ in der Baumstruktur den Platz von $k$ einnimmt (nicht gezeigt).
 \end{enumerate}
diff --git a/304_Halden.tex b/304_Halden.tex
index 31efb68251d6bc52ae6d679f21c8a3993b2b9482..06931fb82e6a58dbde145878002300828ed101f2 100644
--- a/304_Halden.tex
+++ b/304_Halden.tex
@@ -2,7 +2,7 @@
 
 Halden sind eine Datenstrukturen, welche insbesondere zur Implementierung von priority queues geeignert sind, aber auch
 einen worst-case optimalen in-place Sortieralgorithmus bereitstellen. Es gibt zwei Perspektiven auf Halden: Einmal als
-Array und einmal als vollständiger, sortierter Binärbaum:
+Array und einmal als vollständiger Binärbaum:
 
 \begin{definition}[Halde: Arraydefinition]
   Eine Halde $\mathcal{H}$ ist ein Array $\mathcal{A}$ von $n$ Elementen mit einer Quasiordnung, welches der folgenden Haldenbedingung genügt:
@@ -42,41 +42,35 @@ definiert als $h(n) := \floor*{\log_2 n}$. Eine leere Halde hat die Höhe $h(0)
 
 
 \subsection{Verhalden (\texttt{heapify})}
-Der Algorithmus $\texttt{heapify}$ repariert eine Fast-Halde, bei dem die Haldenbedingung an genau einer Stelle $i$ verletzt
-ist. Wir nehmen dabei an, dass der linke und rechte Teilbaum von $i$ Halden sind.
+Der Algorithmus $\texttt{heapify}$ repariert eine Fast-Halde, bei dem die Haldenbedingung an genau an der Wurzel
+beziehungweise im ersten EElement verletzt ist ist. Wir nehmen also an, dass der linke und rechte Teilbaum von $i$ Halden sind.
 
-Um die Haldenbedingung zu erzwingen, muss das $i.$ Element also mit dem Maximum seiner beiden Kinder getauscht werden.
-Ist das $i.$ Element aus Baumperspektive ein Blatt (also $i \geq \frac{n}{2}$), so ist die Haldenbedingung immer erfüllt. 
+Ist das Wurzelelement ein Blatt, so ist die Haldenbedingung immer erfüllt. 
+Um sonst die Haldenbedingung zu erzwingen, muss das Wurzelelement also mit dem Maximum seiner beiden Kinder getauscht werden.
+Dabei wird die Haldenbedingung aber möglicherweise bei betauschten Kindknoten verletzt. Also rufen wir den Algorithmus dort noch einmal auf.
 
-Andernfalls vertauschen wir das  $i.$ Elemente mit maximum seiner Kindknoten. Damit ist bei $i$ die Haldenbedingung
-erfüllt, aber möglicherweise bei einem Kindknoten nun verletzt. Also rufen wir den Algorithmus dort noch einmal auf.
-
-In Pseudocode aus der Array-Perspektive sieht das folgendermaßen aus (Der Pseudocode in Baumperspektive ist eine
+In Pseudocode aus der Array-Perspektive sieht das folgendermaßen aus (Der Pseudocode in Arrayperspektive ist eine
 Übungsaufgabe):
 
 \begin{algorithm}[H]
   \SetNlSty{texttt}{[}{]}
-  \caption{\texttt{heapify}($\mathcal{H}, i$)}
-  \KwIn{An almost-heap $\mathcal{H}$ of size $n$ with above conditions and the index $i \in \{0, \cdots, n-1\}$}
+  \caption{\texttt{heapify}($\mathcal{H}$)}
+  \KwIn{An almost-heap $\mathcal{H}$ with $r := \text{root}(\mathcal{H})$ with above conditions}
   \KwOut{A modified $\mathcal{H}$ with its heap structure intact}
-  $l \leftarrow 2i + 1$ \;
-  $r \leftarrow 2i + 2$ \;
-  $j \leftarrow i$ \;
-  \If{$l < n$ and $\mathcal{H}[l] > \mathcal{H}[i]$}{
-    $j \leftarrow l$ \;
-  }
-  \If{$r < n$ and $\mathcal{H}[r] > \mathcal{H}[j]$}{
-    $j \leftarrow r$ \;
+  $m \leftarrow \max{\texttt{data}(\texttt{left}(r)), \texttt{data}(\texttt{right}(r))}$ \;
+  \If{$m > \texttt{data}(r)$}{
+    \eIf{$\texttt{data}(\texttt{left}(r)) = m$}{
+      $n \leftarrow \texttt{left}(r)$ \;
+    }{
+      $n \leftarrow \texttt{right}(r)$ \;
+    }
+    $\texttt{swap}(\texttt{data}(n), \texttt{data}(r))$ \;
+    $\texttt{heapify}(n)$ \;
   }
-  \If{$i \neq j$}{
-    $\texttt{swap}(\mathcal{H}[i], \mathcal{H}[j])$ \;
-    $\mathcal{H} \leftarrow \texttt{heapify}(\mathcal{H},j)$ \;
-  }
-  \KwRet $\mathcal{H}$
 \end{algorithm}
 
 \paragraph{Korrektheit:}
-Unter obig beschriebenen Bedingungen repariert der Algorithmus den Knoten $i$, möglicherweise auf Kosten der
+Unter obig beschriebenen Bedingungen repariert der Algorithmus den Wurzelknoten, möglicherweise auf Kosten der
 Haldenbedingung auf in einer seiner Kindknoten. Da in dem Fall der Algorithmus rekursiv aufgerufen wird und der
 Basisfall (Knoten ist ein Blatt) die Haldenbedingung trivial erfüllt, terminiert der Algorithmus und arbeitet korrekt.
 
@@ -89,18 +83,20 @@ $\texttt{heapify}$ ohne seine rekursiven Unteraufrufe $c \in \mathcal{O}(1)$ dau
 \subsection{Aufbau einer Halde aus einem Array/Baum}
 
 Wir können aus einem beliebigen Array (oder vollständigen Binärbaum) eine Halde machen, indem wir, angefangen an den
-Blättern bis hin zur Wurzel, immer wieder $\texttt{heapify}$ rufen. Bei den Blättern können wir es uns sparen, da sie eh
-schon Heaps sind. Damit haben wir (in Array-Perspektive) folgenden Pseudocode
+Blättern bis hin zur Wurzel, immer wieder $\texttt{heapify}$ aufrufen.
 
 \begin{algorithm}[H]
   \SetNlSty{texttt}{[}{]}
-  \caption{\texttt{heapify\_array}($\mathcal{A}$)}
-  \KwIn{An array $\mathcal{A}$ of size $n$}
-  \KwOut{The same Array but resorted as a heap}
-  \For{$i \leftarrow \floor*{\frac{n}{2}}$ \KwTo $0$}{
-    $\texttt{heapify}(\mathcal{A}, i)$ \;
+  \caption{\texttt{heapify\_tree}($\mathcal{B}$)}
+  \KwIn{A complete binary tree $\mathcal{B}$ with $r := \text{root}(\mathcal{B})$}
+  \KwOut{The same tree but resorted as a heap}
+  \eIf{$\mathcal{B}$ is a leaf}{
+    \KwRet $\mathcal{B}$ \;
+  }{
+    $\texttt{left}(r) \leftarrow \texttt{heapify\_tree}(\texttt{left}(r))$ \;
+    $\texttt{right}(r) \leftarrow \texttt{heapify\_tree}(\texttt{right}(r))$ \;
+    \KwRet $\texttt{heapify}(\mathcal{B})$ \;
   }
-  \KwRet $\mathcal{A}$
 \end{algorithm}
 
 \paragraph{Korrektheit:}
@@ -108,19 +104,19 @@ Dadurch, dass wir von unten nach oben arbeiten, sind Teilbäume bereits Halden.
 $\texttt{heapify}$ erfüllt und der Algorithmus arbeitet korrekt.
 
 \paragraph{Laufzeit:}
-Die Funktion $\texttt{heapify}$ wird $\frac{n}{2}$ mal aufgerufen und hat selber einen Aufwand von
+Die Funktion $\texttt{heapify}$ wird $n$ mal aufgerufen und hat selber einen Aufwand von
 $\mathcal{O}(\log n)$. Dadurch ist die Abschätzung für den asymptotischen Aufwand von $\texttt{heapify\_array}$ mit
 $\mathcal{O}(n \log n)$ schnell getroffen. Allerdings stellt sich heraus, dass man auch exakter abschätzen kann, da die
 Laufzeit von $\texttt{heapify}$ nicht immer der Höhe des kompletten Baumes entspricht. Dadurch erreicht man eine
-genauere Abschätzung: Die Laufzeit von $\texttt{heapify\_array}(\mathcal{A})$  liegt in $Θ(n)$, wobei $n$ die Länge des
-Array $\mathcal{A}$ ist (Übungsaufgabe).
+genauere Abschätzung: Die Laufzeit von $\texttt{heapify\_tree}(\mathcal{A})$  liegt in $Θ(n)$, wobei $n$ die Größe des
+Baumes $\mathcal{B}$ ist (Übungsaufgabe).
 
 
 \subsection{Sortieren mit Halden (Heapsort)}
 Mit Hilfe der beiden vorherigen Algorithmen kann man auch einen Sortieralgorithmus konstruieren. Wir starten mit einem
 Array/Baum und formen ihn in eine Halde um. An der Wurzel des Baumes bzw dem Anfang des Arrays haben wir dann das
 Maximum aller Elemente. Dieses Element gilt als sortiert und wird mit dem letzten Platz des Arrays vertauscht, welcher
-nun nichtmehr angefasst wird. Ein erneuter Aufruf von $\texttt{heapify}$ findet wieder das Maximum, wir vertauschen mit
+nun nicht mehr angefasst wird. Ein erneuter Aufruf von $\texttt{heapify}$ findet wieder das Maximum, wir vertauschen mit
 dem vorletzten Feld, etc. 
 Damit haben wir ein worst-case optimalen in-place Sortieralgorithmus:
 
@@ -152,6 +148,13 @@ n)$ hat. Die Laufzeit wird von den $\frac{n}{2}$ aufrufen von $\texttt{heapify}$
 hat, eh dominiert. Also liegt die Laufzeit in $\mathcal{O}(n \log n)$. Damit ist $\texttt{heapsort}$ also worst-case
 optimal. 
 
+\paragraph{Eigenschaften:}
+Der Algorithmus \texttt{heapsort} arbeitet in-place, solang man Zeile [1] in-place hinbekommt (Übungsaufgabe).
+Desweiteren ist er worst-case-optimal. Allerdings ist er nicht stabil (Übungsaufgabe) und durch das initiale Verhalden
+auch nicht adaptiv.
+Desweiteren wird (ungeschickterweise) sehr häufig ein besonders kleines Element an die Spitze getauscht, womit sich auch
+die echte Laufzeit, abseits von asymptotischer Analyse, unattraktiv verhält.
+
 \begin{figure}[H]
   \centering
   \input{bilder/heapsort_1.tex}
@@ -182,18 +185,19 @@ optimal.
 \begin{figure}[H]
   \centering
   \input{bilder/heapsort_4.tex}
-  \caption{Der Algorithmus \texttt{heapsort} auf den Array $\mathcal{A} = [5,7,3,1,8,2]$. Im dritten Schritt wird
-    \texttt{heapify} auf den Knoten mit dem Wert $7$ ausgeführt, also die Haldenbedingung zu seinem Unterbaum
-    überprüft und gegenbenenfalls repariert. Da $8$ größer ist als $7$, werden die beiden Werte getauscht.}
+  \caption{Der Algorithmus \texttt{heapsort} auf den Array $\mathcal{A} = [5,7,3,1,8,2]$. Im vierten Schritt wird
+    \texttt{heapify} auf den (getauschten) Knoten mit dem Wert $5$ ausgeführt, also die Haldenbedingung zu seinem Unterbaum
+    überprüft und gegenbenenfalls repariert. Da $7$ größer ist als $5$, werden die beiden Werte getauscht.}
   \label{fig:heapsort_4}
 \end{figure}
 
 \begin{figure}[H]
   \centering
   \input{bilder/heapsort_5.tex}
-  \caption{Der Algorithmus \texttt{heapsort} auf den Array $\mathcal{A} = [5,7,3,1,8,2]$. Im dritten Schritt wird
-    \texttt{heapify} auf den Knoten mit dem Wert $7$ ausgeführt, also die Haldenbedingung zu seinem Unterbaum
-    überprüft und gegenbenenfalls repariert. Da $8$ größer ist als $7$, werden die beiden Werte getauscht.}
+  \caption{Der Algorithmus \texttt{heapsort} auf den Array $\mathcal{A} = [5,7,3,1,8,2]$. Im fünften und letzten Schritt wird
+    \texttt{heapify} auf den Knoten mit dem Wert $5$ ausgeführt, also die Haldenbedingung zu seinem Unterbaum
+    überprüft und gegenbenenfalls repariert. Da es sich hierbei um ein Blatt handelt, ist $\texttt{heapify}$ fertig und
+    damit auch $\texttt{heapify\_tree}$}.
   \label{fig:heapsort_5}
 \end{figure}
 
@@ -212,7 +216,39 @@ optimal.
 \subsection{Wartschlange (Priority Queue)*}
 Eine der häufigsten Anwendungen von Halden: Warteschlangen mit einer Priorität, bei der immer das dringenste (also das
 größte) Element gesucht wird. Da das sofort das erste Arrayelement ist, kommt der Vorteil von Halden voll zum tragen.
-Einfügen und Löschen erfolgt mit $\mathcal{O}(\log n)$ aufwand, wie bei Baumstrukturen üblich.
-
-TODO: Details
-
+Einfügen und Löschen erfolgt mit $\mathcal{O}(\log n)$ Aufwand, wie bei Baumstrukturen üblich.
+
+%
+%\begin{algorithm}[H]
+%  \SetNlSty{texttt}{[}{]}
+%  \caption{\texttt{heapify}($\mathcal{H}, i$)}
+%  \KwIn{An almost-heap $\mathcal{H}$ of size $n$ with above conditions and the index $i \in \{0, \cdots, n-1\}$}
+%  \KwOut{A modified $\mathcal{H}$ with its heap structure intact}
+%  $l \leftarrow 2i + 1$ \;
+%  $r \leftarrow 2i + 2$ \;
+%  $j \leftarrow i$ \;
+%  \If{$l < n$ and $\mathcal{H}[l] > \mathcal{H}[i]$}{
+%    $j \leftarrow l$ \;
+%  }
+%  \If{$r < n$ and $\mathcal{H}[r] > \mathcal{H}[j]$}{
+%    $j \leftarrow r$ \;
+%  }
+%  \If{$i \neq j$}{
+%    $\texttt{swap}(\mathcal{H}[i], \mathcal{H}[j])$ \;
+%    $\mathcal{H} \leftarrow \texttt{heapify}(\mathcal{H},j)$ \;
+%  }
+%  \KwRet $\mathcal{H}$
+%\end{algorithm}
+%
+%
+%\begin{algorithm}[H]
+%  \SetNlSty{texttt}{[}{]}
+%  \caption{\texttt{heapify\_array}($\mathcal{A}$)}
+%  \KwIn{An array $\mathcal{A}$ of size $n$}
+%  \KwOut{The same Array but resorted as a heap}
+%  \For{$i \leftarrow \floor*{\frac{n}{2}}$ \KwTo $0$}{
+%    $\texttt{heapify}(\mathcal{A}, i)$ \;
+%  }
+%  \KwRet $\mathcal{A}$
+%\end{algorithm}
+%