## 1. Dynamische Datenstrukturen ### Linked-List $$self.address: A[i] $$ $$\longleftarrow prev.address \ | \ next.address\longrightarrow$$ ### Stack First-In; Last-Out ### Binary-Tree $$self.address : Value$$ $$\rightarrow left.address : \rightarrow right.address$$ ### Graphen #### Adjazenzmatrix Von *Zeile* nach *Spalte* $$ \newcommand\T{\rlap{\text{to}}} \begin{array}{cc} & \T \\ \text{from} & \begin{array}{c|cccc} & v_0 & v_1 & v_2 & v_3 \\ \hline v_0 & 0 & 1 & 1 & 0 \\ v_1 & 0 & 0 & 0 & 0 \\ v_2 & 0 & 1 & 0 & 0 \\ v_3 & 0 & 0 & 1 & 1 \\ \end{array} \end{array} $$ #### Adjazenzliste Von Spaltenheader zu allen elementen in der Spalte $$ \begin{array} & 1 & 2 & 3 & 4 \\ \hline 2 & 3 & 2 & 1 \\ 4 \\ \end{array} $$ ## 2. Skipliste, Binary-Search-Tree, Shellsort ### Skipliste $$ \begin{array}{l} \text{Layer 2:} \quad H \rightarrow \phantom{E_1 \rightarrow E_2 \rightarrow} E_3 \rightarrow \phantom{E_4 \rightarrow E_5 \rightarrow} \text{NIL} \\ \\ \text{Layer 1:} \quad H \rightarrow E_1 \rightarrow \phantom{E_2 \rightarrow} E_3 \rightarrow \phantom{E_4 \rightarrow} E_5 \rightarrow \text{NIL} \\ \\ \text{Layer 0:} \quad H \rightarrow E_1 \rightarrow E_2 \rightarrow E_3 \rightarrow E_4 \rightarrow E_5 \rightarrow \text{NIL} \end{array} $$ ### Binary Search Tree >Linker Teilbaum *kleiner*, rechter Teilbaum *größer* $$Tiefe = Max(\text{Anzahl Kanten})$$ **Suchen** Richtung? -> Vergleich von beiden Kinder knoten **Einfügen** Gleich wie suchen **Löschen** Pointer umsetzen ### Shellsort #### Insertionsort **Schritt-für-Schritt:** 1. Beginne mit dem zweiten Element (Index 1) im Array. Das erste Element gilt als bereits sortiert. 2. Vergleiche das aktuelle Element mit den vorherigen Elementen. 3. Wenn das aktuelle Element kleiner als das verglichene Element ist, verschiebe das verglichene Element um eine Position nach rechts. 4. Wiederhole Schritt 3, bis du die richtige Position für das aktuelle Element gefunden hast. 5. Füge das aktuelle Element an der richtigen Stelle ein. 6. Gehe zum nächsten Element und wiederhole die Schritte 2–5, bis das Array sortiert ist. **Beispiel:** Angenommen, du hast das Array: [5, 2, 9, 1] - Beginne mit 2 (Index 1). Vergleiche mit 5. Da 2 < 5, verschiebe 5 nach rechts und setze 2 an Index 0. Jetzt: [2, 5, 9, 1] - Als Nächstes 9 (Index 2). Vergleiche mit 5. 9 > 5, also bleibt alles wie es ist. - Als Nächstes 1 (Index 3). Vergleiche mit 9, 5 und 2. 1 < 9, 1 < 5, 1 < 2. Verschiebe alle drei nach rechts und setze 1 an Index 0. Jetzt: [1, 2, 5, 9] #### Shellsort ##### Schrittweite Wahrscheinlich in der Aufgabe gegeben, ansonsten die hier nehmen: $$s_i = 2^i -1$$ - Mit Schrittweite in Sub-Arrays zerlegen. - Diese Schritt-Arrays mit Insertionsort sortieren. - Bei Schrittweite 1 Durchlauf endet die Sortierung. ## 3. Heaps und Heapsort Ein heap ist ein binary tree, bei dem alle Elternknoten bei einem Max-Heap, größer Werden respektiv bei einem Min-Heap kleiner Min-Heap = Oben das kleinste Max-Heap = Oben das größte Tiefe: $$floor(\log_2(n))+1$$ Index von Kindern und Parent: $$ \text{Children}: \begin{cases}   2i & \text{Child 1} \\   2i+1  & \text{Child 2 } \end{cases} $$ $$Parent: floor\left(\frac{2i}{2}\right)$$ ### Max/Min-Heap-Reparieren: Man itereriert durch alle Element, ausgeschlossen die Blätter. Folgendes Schema: >**Breadth-First**: Man startet dem Letzten Element (Visuell unten rechts), das **Kinder** hat. Dann nach Links bis ende der Ebene und dann nach oben. Das ist nur das Iterieren! Noch Reparieren! ```python for e in Elements: ... ``` Schicht 1 $\longleftarrow\longleftarrow Root \longleftarrow \longleftarrow\Lsh$ Schicht 2 $\longleftarrow\longleftarrow e_1 \longleftarrow e_2 \longleftarrow\Lsh$ Schicht 3 $\leftarrow e_3 \leftarrow e_4 \leftarrow e_5 \leftarrow e_6 \leftarrow \text{START}$ ... Blätter .................................................. Jedes Element das man anschaut wird dann *down-geshifted*. Im grunde Rekursives Max/Min im Dreieck. 1. Man vergleicht aktuelles Element mit den Kindern. (Wie so ein Dreieck) ```tikz \begin{document} \begin{tikzpicture}[level distance=1.5cm, level 1/.style={sibling distance=3cm}, level 2/.style={sibling distance=1.5cm}] \node {element} child {node {child 1}} child {node {child 2}}; \end{tikzpicture} \end{document} ``` 2. (Abbruchbedingung), Gehe zum nächsten Element ... 1. Max-Heap: Wenn $element$ ist das **größte** von den drei: $max([e, c1, c2]) = e$ 2. Min-Heap: Wenn $element$ ist das **kleinste** von den drei: $min([e, c1, c2]) = e$ 3. Wenn nicht, dann *tausche* mit dem größten (Max-Heap) / kleinsten (Min-Heap) der drei. 4. Wiederhole, bis Abbruchbedingung erreicht, oder ende vom Baum, bzw. ganz unten. #### Heap-Sort 1. Unten Rechts (Letztes Element im Heap-Array, ist ein Blatt btw.), mit dem ersten (Root) Tauschen. 2. Heap Reparieren indem man das neue Root element **down-shifted**, bis es wieder am richtigen platz ist, siehe vorherige erklärung. ## 4. Balancierte Bäume Binärer Suchbaum Max. Tiefe: $log_2(n)$ Jeder Knoten bekommt einen *Balancefaktor*, dieser Entspricht der Tiefe vom rechten, minus der Tiefe des linken Teilbaumes. > Tiefe von einem (Teil)Baum, ist einfach die maximale Anzahl Kanten nach unten. $$BAL(N) = T(u_2) - T(u_1)$$ Dieser sollte $$-1 \leq BAL(N)\leq 1$$ ## 5. Reelwertige Optimierung in einer Dimension Bisektion mit Sampling. I.e. man macht Bisektion mehrere Male, mit anderen Intervallen. Ganz Normal Newton Verfahren mit Schrittweitensteuerung. ## 6. Bivariate Lineare Programmierung 1. Nebenbedingungen Aufbauen (Ungleichungen) 2. Nach $y$ auflösen und einzeichnen 3. Lösung finden ## 7. Reelwertige Optimierung in N Dimensionen $$f(x_1, x_2,..., x_n)$$ $$ f'(x) \longrightarrow \nabla f(x)$$ $$f''(x) \longrightarrow H$$ TODO: hesse matrix ### 7.2 Downhill-Simplex Besteht aus n+1 Punkten **Vorgehen**: 1. Berechne alle $f(x_0), f(x_1), \ ...$ 2. Berechne Schwerpunkt (Durchschnitt von allen $x$) 3. Eine Operation ausführen #### Reflection Spiegelung des *schlechtesten* Punktes am Schwerpunkt $$x_r = x_{n+1} + (x_{n+1}-\bar{x})$$ #### Expansion Spiegelung aber *skaliert* #### Contraction #### Shrinkage Zieht die schlechten Punkten zum besten Punkt. I.e. halbiert die Entfernung zum besten Punkt. #### Abbruch $$f_{worst} - f_{best} < tol$$ $$\sqrt{mean((f_{x_i} -f_S)^2)} < tol$$ $$mean((f_{x_i} - mean([...f_x]))^2)$$ ### 7.3 Newton Für 1 Parameter: $$x_{n+1} = x_n - \frac{f'(x)}{f''(x)}$$ Für 1< Parameter: $$x_{x+1} = x_n - H^{-1}_n * \nabla f_n$$ Mit Schrittweitensteuerung: $$x_{x+1} = x_n - c_i * H^{-1}_n * \nabla f_n$$ Straffunktion: Sei $A \leq x \leq B$ eine Restriktion für ein Optimierungsproblem. Dann kann man die Restriktion $A \leq x \leq B$ in das Optimierungsproblem mittels einer Straf- bzw. Penaltyfunktion einbauen. Eine häufig verwendete Methode ist die quadratische Strafterm-Methode: $$ \phi(x) = f(x) + \mu \cdot \left( \sum_i \max(0, A_i - x_i)^2 + \sum_i \max(0, x_i - B_i)^2 \right) $$ Dabei ist: - $f(x)$ die ursprüngliche Zielfunktion, - $\mu > 0$ ein Strafparameter, der die Stärke der Strafe reguliert, - $A_i$, $B_i$ die untere bzw. obere Schranke für $x_i$. Ziel ist es, eine neue Funktion $\phi(x)$ zu minimieren, die außerhalb des zulässigen Bereichs stark anwächst, sodass die Minimierung bevorzugt innerhalb der Restriktionen erfolgt. ### 7.4 Steepest-Descent Newton aber mit Hesse-Matrix = 1 $$x_{x+1} = x_n - c_i * \nabla f_n$$