diff --git a/20210211/aufgabe-1.c b/20210211/aufgabe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..82e5b1ca9e2f896bcbec98bc5c34cdf15d086e26 --- /dev/null +++ b/20210211/aufgabe-1.c @@ -0,0 +1,53 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = pos; i < stack_pointer; i++) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = 0; + while (i < stack_pointer && x < stack[i]) + i++; + insert (x, i); +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; +} diff --git a/20210211/aufgabe-2.c b/20210211/aufgabe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..f26ce5d665012e2cdbaac8b0f43f01d40f338254 --- /dev/null +++ b/20210211/aufgabe-2.c @@ -0,0 +1,47 @@ +#include <stdio.h> +#include <stdlib.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +void output_list (node *first) +{ + for (node *p = first; p; p = p->next) + printf ("%d ", p->content); + printf ("\n"); +} + +void insert_into_list (node *what, node *where) +{ + what->next = where->next; + where->next = what; +} + +int main (void) +{ + node *element3 = malloc (sizeof (node)); + node *element7 = malloc (sizeof (node)); + node *element137 = malloc (sizeof (node)); + + element3->content = 3; + element7->content = 7; + element137->content = 137; + + node *first = element3; + element3->next = element7; + element7->next = element137; + element137->next = NULL; + + output_list (first); + + node *element5 = malloc (sizeof (node)); + element5->content = 5; + insert_into_list (element5, element3); + + output_list (first); + + return 0; +} diff --git a/20210211/baeume-1.txt b/20210211/baeume-1.txt new file mode 100644 index 0000000000000000000000000000000000000000..c397a0bfab179bee2d9cf5fb74731fc89b8337ed --- /dev/null +++ b/20210211/baeume-1.txt @@ -0,0 +1,20 @@ +Zahlen von 0 bis 14 in einem Baum + +best case: O(log n) - "ausbalancierter Baum" + + 7 + + + 3 11 + 1 5 9 13 + 0 2 4 6 8 10 12 14 + +worst case: O(n) - "entarteter Baum" + + 0 + 1 + 2 + 3 + 4 + ... + 14 diff --git a/20210211/fifo-1.c b/20210211/fifo-1.c new file mode 100644 index 0000000000000000000000000000000000000000..8bce6c07c152381c11ce367027b980a9330be3e0 --- /dev/null +++ b/20210211/fifo-1.c @@ -0,0 +1,31 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + return fifo[0]; + fifo[0] = fifo[1]; + fifo[1] = fifo[2]; + fifo[2] = fifo[3]; + /* ... */ +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-2.c b/20210211/fifo-2.c new file mode 100644 index 0000000000000000000000000000000000000000..f95579893f62180b408ecb10756ac8938b3c9848 --- /dev/null +++ b/20210211/fifo-2.c @@ -0,0 +1,31 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + fifo[0] = fifo[1]; + fifo[1] = fifo[2]; + fifo[2] = fifo[3]; + /* ... */ + return fifo[0]; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-3.c b/20210211/fifo-3.c new file mode 100644 index 0000000000000000000000000000000000000000..5214e1b28fb1b060bdaeea7be09e346a644e7f5d --- /dev/null +++ b/20210211/fifo-3.c @@ -0,0 +1,32 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + int result = fifo[0]; + fifo[0] = fifo[1]; + fifo[1] = fifo[2]; + fifo[2] = fifo[3]; + /* ... */ + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-4.c b/20210211/fifo-4.c new file mode 100644 index 0000000000000000000000000000000000000000..957d5f18f6c8fe9d7c057db3d2467221b9dc463e --- /dev/null +++ b/20210211/fifo-4.c @@ -0,0 +1,30 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + int result = fifo[0]; + for (int i = 1; i < FIFO_SIZE; i++) + fifo[i - 1] = fifo[i]; + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-5.c b/20210211/fifo-5.c new file mode 100644 index 0000000000000000000000000000000000000000..092c1cdb5863d5c7bdac98f48ca8527ca3520e6b --- /dev/null +++ b/20210211/fifo-5.c @@ -0,0 +1,32 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + int result = fifo[0]; + for (int i = 1; i < FIFO_SIZE; i++) + fifo[i - 1] = fifo[i]; + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-6.c b/20210211/fifo-6.c new file mode 100644 index 0000000000000000000000000000000000000000..2f055d6ce6df4c2fca950192053a6e008bed38b4 --- /dev/null +++ b/20210211/fifo-6.c @@ -0,0 +1,33 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + int result = fifo[0]; + for (int i = 1; i < FIFO_SIZE; i++) + fifo[i - 1] = fifo[i]; + fifo_pointer--; + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-6a.c b/20210211/fifo-6a.c new file mode 100644 index 0000000000000000000000000000000000000000..6a7b2d3c138908cb7eb06379b9c574f262717af0 --- /dev/null +++ b/20210211/fifo-6a.c @@ -0,0 +1,33 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_pointer = 0; + +void push (int x) +{ + fifo[fifo_pointer++] = x; +} + +int pop (void) +{ + int result = fifo[0]; + for (int i = 1; i < fifo_pointer; i++) + fifo[i - 1] = fifo[i]; + fifo_pointer--; + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-7.c b/20210211/fifo-7.c new file mode 100644 index 0000000000000000000000000000000000000000..0d739115c136639f64c4d98c439af7e4d72fe420 --- /dev/null +++ b/20210211/fifo-7.c @@ -0,0 +1,35 @@ +#include <stdio.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_write_pointer = 0; +int fifo_read_pointer = 0; + +void push (int x) +{ + fifo[fifo_write_pointer++] = x; + if (fifo_write_pointer >= FIFO_SIZE) + fifo_write_pointer = 0; +} + +int pop (void) +{ + int result = fifo[fifo_read_pointer++]; + if (fifo_read_pointer >= FIFO_SIZE) + fifo_read_pointer = 0; + return result; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-8.c b/20210211/fifo-8.c new file mode 100644 index 0000000000000000000000000000000000000000..b4ff68713645e0a5782b516071022bf71a8c50ac --- /dev/null +++ b/20210211/fifo-8.c @@ -0,0 +1,50 @@ +#include <stdio.h> +#include <stdlib.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_write_pointer = 0; +int fifo_read_pointer = 0; + +void push (int x) +{ + fifo[fifo_write_pointer++] = x; + if (fifo_write_pointer >= FIFO_SIZE) + fifo_write_pointer = 0; + if (fifo_write_pointer == fifo_read_pointer) + { + fprintf (stderr, "fifo overflow\n"); + exit (1); + } +} + +int pop (void) +{ + if (fifo_read_pointer == fifo_write_pointer) + { + fprintf (stderr, "fifo underflow\n"); + exit (1); + } + else + { + int result = fifo[fifo_read_pointer++]; + if (fifo_read_pointer >= FIFO_SIZE) + fifo_read_pointer = 0; + return result; + } +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/fifo-9.c b/20210211/fifo-9.c new file mode 100644 index 0000000000000000000000000000000000000000..27f77412bac52fd70c52378c25531f03bd93d734 --- /dev/null +++ b/20210211/fifo-9.c @@ -0,0 +1,55 @@ +#include <stdio.h> +#include <stdlib.h> + +#define FIFO_SIZE 10 + +int fifo[FIFO_SIZE]; +int fifo_write_pointer = 0; +int fifo_read_pointer = 0; + +void push (int x) +{ + int old_fifo_write_pointer = fifo_write_pointer; + fifo_write_pointer++; + if (fifo_write_pointer >= FIFO_SIZE) + fifo_write_pointer = 0; + if (fifo_write_pointer == fifo_read_pointer) + { + fprintf (stderr, "fifo overflow\n"); + exit (1); + } + else + fifo[old_fifo_write_pointer] = x; +} + +int pop (void) +{ + if (fifo_read_pointer == fifo_write_pointer) + { + fprintf (stderr, "fifo underflow\n"); + exit (1); + } + else + { + int result = fifo[fifo_read_pointer++]; + if (fifo_read_pointer >= FIFO_SIZE) + fifo_read_pointer = 0; + return result; + } +} + +int main (void) +{ + push (3); + push (7); + push (137); + for (int i = 0; i < 42; i++) + push (i); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + push (42); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/hello-gtk.png b/20210211/hello-gtk.png new file mode 120000 index 0000000000000000000000000000000000000000..cca99209d86683a9a3b0f70bbc149780bae10ba6 --- /dev/null +++ b/20210211/hello-gtk.png @@ -0,0 +1 @@ +../common/hello-gtk.png \ No newline at end of file diff --git a/20210211/hp-20210211.pdf b/20210211/hp-20210211.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1a7c24d02c73d27c93d48f4e4eb307e255ec0952 Binary files /dev/null and b/20210211/hp-20210211.pdf differ diff --git a/20210211/hp-20210211.tex b/20210211/hp-20210211.tex new file mode 100644 index 0000000000000000000000000000000000000000..e7641ee2847378b4e1e5b17bb60f1ffa2bf79d62 --- /dev/null +++ b/20210211/hp-20210211.tex @@ -0,0 +1,1187 @@ +% hp-20210211.pdf - Lecture Slides on Low-Level Programming +% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Objektorientierte Programmierung: virtuelle Methoden + +\documentclass[10pt,t]{beamer} + +\usepackage{pgslides} +\usepackage{rotating} +\usepackage{tikz} + +\title{Hardwarenahe Programmierung} +\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski} +\date{11.\ Februar 2021} + +\begin{document} + +\maketitleframe + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \begin{itemize} + \item[6.0] Dynamische Speicherverwaltung + \item[6.1] Konzepte und Ziele + \item[6.2] Beispiel: Zahlen und Buchstaben + \item[6.3] Unions + \color{medgreen} + \item[6.4] Virtuelle Methoden + \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI) + \item[6.6] Ausblick: C++ + \end{itemize} + \item[\textbf{7}] \textbf{Datenstrukturen} + \vspace*{-1cm} + \end{itemize} + +\end{frame} + +\setcounter{section}{5} +\section{Objektorientierte Programmierung} + +\addtocounter{subsection}{-1} +\subsection{Dynamische Speicherverwaltung} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{itemize} + \item + Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen) + \item + Dynamisches Array: variable Anzahl von Elementen desselben Typs + \end{itemize} + + \bigskip + + \begin{lstlisting} + char *name[] = { "Anna", "Berthold", "Caesar" }; + + ... + + name[3] = "Dieter"; + \end{lstlisting} + + \begin{picture}(0,0) + \color{red} + \put(0,0){\line(3,1){3.5}} + \put(0,1){\line(3,-1){3.5}} + \end{picture} + +\end{frame} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \bigskip + + \begin{lstlisting} + #include <stdlib.h> + + ... + + char **name = malloc (3 * sizeof (char *)); + /* Speicherplatz für 3 Zeiger anfordern */ + + ... + + free (name); + /* Speicherplatz freigeben */ + + \end{lstlisting} + +\end{frame} + +\subsection{Konzepte und Ziele} + +\begin{frame} + + \showsection + \showsubsection + + \begin{itemize} + \item +% Array: feste Anzahl von Elementen desselben Typs (z.\,B.\ 3 ganze Zahlen) + Array: Elemente desselben Typs (z.\,B.\ 3 ganze Zahlen) +% \item +% Dynamisches Array: variable Anzahl von Elementen desselben Typs + \item + Problem: Elemente unterschiedlichen Typs + \item + Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt} + \item + Problem: Die Elemente sind unterschiedlich groß (Speicherplatz). + \item + Lösung: Im Array nicht die Objekte selbst speichern, sondern Zeiger darauf. + \end{itemize} + \begin{itemize} + \item + Funktionen, die mit dem Objekt arbeiten: \newterm{Methoden} + \begin{onlyenv}<1> + \item + Was die Funktion bewirkt,\\ + hängt vom Typ des Objekts ab + \item + Realisierung über endlose \lstinline{if}-Ketten + \end{onlyenv} + \begin{onlyenv}<2> + \item + Was die Funktion bewirkt + \begin{picture}(0,0) + \color{red} + \put(-4.00,-0.05){\tikz{\draw[thick](0,0.25)--(3.75,-0.05);% + \draw[thick](-0.1,-0.05)--(3.75,0.3);}} + \end{picture}% + Welche Funktion aufgerufen wird,\\ + hängt vom Typ des Objekts ab: \newterm{virtuelle Methode} + \item + Realisierung über endlose \lstinline{if}-Ketten% + \begin{picture}(0,0) + \color{red} + \put(-2.75,-0.05){\tikz{\draw[thick](0,0.25)--(2.5,-0.05);% + \draw[thick](-0.1,-0.05)--(2.5,0.3);}} +% \put(1.5,-1.1){\begin{rotate}{7}\large\bf\textarrow\ +% kommt gleich +% nächste Woche +% \end{rotate}} + \end{picture} + Zeiger, die im Objekt gespeichert sind\\ + (Genaugenommen: Tabelle von Zeigern) + \end{onlyenv} + \end{itemize} + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \begin{itemize} + \item + Problem: Elemente unterschiedlichen Typs + \item + Lösung: den Typ des Elements zusätzlich speichern \textarrow\ \newterm{Objekt} + \item + \newterm{Methoden\/} und \newterm{virtuelle Methoden} + \end{itemize} + + \begin{itemize} + \item + Zeiger auf verschiedene Strukturen\\ + mit einem gemeinsamen Anteil von Datenfeldern\\ + \textarrow\ "`verwandte"' \newterm{Objekte}, \newterm{Klassenhierarchie} von Objekten + \item + Struktur, die \emph{nur\/} den gemeinsamen Anteil enthält\\ + \textarrow\ "`Vorfahr"', \newterm{Basisklasse}, \newterm{Vererbung} + \item +% Explizite Typumwandlung eines Zeigers auf die Basisklasse\\ +% in einen Zeiger auf die \newterm{abgeleitete Klasse}\\ +% \textarrow\ Man kann ein Array unterschiedlicher Objekte\\ +% \strut\phantom{\textarrow} in einer Schleife abarbeiten.\\ + Zeiger auf die Basisklasse dürfen auf Objekte\\ + der \newterm{abgeleiteten Klasse} zeigen\\ + \textarrow\ \newterm{Polymorphie} + \end{itemize} + +\end{frame} + +\subsection{Beispiel: Zahlen und Buchstaben} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage}\\[0.7cm] + \begin{onlyenv}<1> + \begin{minipage}{8cm} + \begin{lstlisting}[gobble=10] + ¡t_integer i = { 1, 42 }; + t_string s = { 2, "Hello, world!" }; + + t_base *object[] = { (t_base *) &i, (t_base *) &s };¿ + \end{lstlisting} + \end{minipage}% + \begin{picture}(0,0) + \color{red} + \put(-5.4,-0.8){\mbox{$\underbrace{\rule{1.45cm}{0pt}}_{\shortstack{\strut explizite\\Typumwandlung}}$}} + \end{picture} + \end{onlyenv} +% \begin{onlyenv}<2> +% \begin{minipage}{5cm} +% \begin{lstlisting}[gobble=10] +% ¡typedef union +% { +% t_base base; +% t_integer integer; +% t_string string; +% } t_object;¿ +% \end{lstlisting} +% \end{minipage} +% \end{onlyenv} + \end{center} + +\end{frame} + +\subsection{Unions} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + int8_t i; + uint8_t u; + } num8_t;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{4.5cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + num8_t test; + test.i = -1; + printf ("%d\n", test.u); + return 0; + }¿ + \end{lstlisting} + \end{minipage} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + char s[8]; + uint64_t x; + } num_char_t;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{4.5cm} + \begin{lstlisting}[gobble=6] + ¡int main (void) + { + num_char_t test = { "Hello!" }; + printf ("%lx\n", test.x); + return 0; + }¿ + \end{lstlisting} + \end{minipage} + +\end{frame} + +\begin{frame}[fragile] + + \showsubsection + + Variable teilen sich denselben Speicherplatz. + + \medskip + + \begin{minipage}[t]{3.7cm} + \begin{lstlisting}[gobble=6] + ¡typedef union + { + t_base base; + t_integer integer; + t_string string; + } t_object;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + } t_base;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage}% + \begin{minipage}[t]{3.0cm} + \begin{lstlisting}[gobble=6] + + ¡typedef struct + { + int type; + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + + \bigskip + + \begin{center} + \begin{minipage}{8.5cm} + \begin{lstlisting}[gobble=8] + ¡tobject *this; + + if (this->base.type == T_INTEGER) + printf ("Integer: %d\n", this->integer.content); + else if (this->base.type == T_STRING) + printf ("String: \"%s\"\n", this->string.content);¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\subsection{Virtuelle Methoden} + +\begin{frame}[fragile] + \showsubsection + + \begin{lstlisting} + void print_object (t_object *this) + { + if (this->base.type == T_INTEGER) + printf ("Integer: %d\n", this->integer.content); + else if (this->base.type == T_STRING) + printf ("String: \"%s\"\n", this->string.content); + } + \end{lstlisting} + + \begin{picture}(0,0) + \color{red} + \put(9,1.7){\shortstack[l]{if-Kette:\\\strut wird unübersichtlich}} + \put(1,-2){\mbox{\textarrow}} + \put(0,-3){\mbox{Zeiger auf Funktionen}} + \end{picture} + + \begin{lstlisting}[xleftmargin=4cm] + void print_integer (t_object *this) + { + printf ("Integer: %d\n", this->integer.content); + } + + void print_string (t_object *this) + { + printf ("String: \"%s\"\n", this->string.content); + } + \end{lstlisting} + +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + Zeiger auf Funktionen + + \medskip + + \begin{lstlisting} + void (* print) (t_object *this); + \end{lstlisting} + \begin{picture}(0,1.2)(0,-0.9) + \color{red} + \put(0.95,0.3){\mbox{$\underbrace{\rule{1cm}{0pt}}$}} + \put(0.2,-0.7){\shortstack{das, worauf print zeigt,\\ist eine Funktion}} + \end{picture} + + \begin{itemize} + \item + Objekt enthält Zeiger auf Funktion + \begin{onlyenv}<1> + \medskip + \begin{lstlisting}[gobble=10] + typedef struct + { + void (* print) (union t_object *this); + int content; + } t_integer; + \end{lstlisting} + \vspace*{-1cm} + \end{onlyenv} + \begin{onlyenv}<2-> + \vspace*{-3.5cm} % Why doesn't a picture environment work here??? :-( + \begin{lstlisting}[gobble=10,xleftmargin=5.5cm] + typedef struct + { + void (* print) (union t_object *this); + int content; + } t_integer; + \end{lstlisting} + \vspace*{0.85cm} + \bigskip + \smallskip + \end{onlyenv} + \pause + \item + Konstruktor initialisiert diesen Zeiger + \begin{onlyenv}<2> + \medskip + \begin{lstlisting}[gobble=10] + t_object *new_integer (int i) + { + t_object *p = malloc (sizeof (t_integer)); + p->integer.print = print_integer; + p->integer.content = i; + return p; + } + \end{lstlisting} + \vspace*{-2cm} + \end{onlyenv} + \pause + \item + Aufruf: "`automatisch"' die richtige Funktion + \begin{onlyenv}<3> + \medskip + \begin{lstlisting}[gobble=10] + for (int i = 0; object[i]; i++) + object[i]->base.print (object[i]); + \end{lstlisting} + \end{onlyenv} + \pause + \medskip + \item + in größeren Projekten:\\ + Objekt enthält Zeiger auf Tabelle von Funktionen + \end{itemize} +\end{frame} + +\subsection{Beispiel: Graphische Benutzeroberfläche (GUI)} + +\begin{frame}[fragile] + + \showsubsection + + \scriptsize + \begin{lstlisting} + #include <gtk/gtk.h> + + int main (int argc, char **argv) + { + gtk_init (&argc, &argv); + GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW (window), "Hello"); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL); + GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 10); + GtkWidget *label = gtk_label_new ("Hello, world!"); + gtk_container_add (GTK_CONTAINER (vbox), label); + GtkWidget *button = gtk_button_new_with_label ("Quit"); + g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL); + gtk_container_add (GTK_CONTAINER (vbox), button); + gtk_widget_show (button); + gtk_widget_show (label); + gtk_widget_show (vbox); + gtk_widget_show (window); + gtk_main (); + return 0; + } + \end{lstlisting} + + \vspace*{-6cm}\strut\hfill + \includegraphics[scale=0.85]{hello-gtk.png}\\[2cm] + \begin{flushright} + \normalsize\bf Praktikumsversuch:\\ + Objektorientiertes Zeichenprogramm + \end{flushright} + +\end{frame} + +\subsection{Ausblick: C++} + +\begin{frame}[fragile] + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (union t_object *this); + } t_base;¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5.5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (...); + int content; + } t_integer;¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡typedef struct + { + void (* print) (union t_object *this); + char *content; + } t_string;¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\begin{frame}[fragile] + \showsubsection + + \begin{center} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡struct TBase + { + virtual void print (void); + };¿ + \end{lstlisting} + \end{minipage}\\[0.5cm] + \begin{minipage}{5.5cm} + \begin{lstlisting}[gobble=8] + ¡struct TInteger: public TBase + { + virtual void print (void); + int content; + };¿ + \end{lstlisting} + \end{minipage} + \begin{minipage}{5cm} + \begin{lstlisting}[gobble=8] + ¡struct TString: public TBase + { + virtual void print (void); + char *content; + };¿ + \end{lstlisting} + \end{minipage} + \end{center} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \begin{itemize} + \item[6.0] Dynamische Speicherverwaltung + \item[6.1] Konzepte und Ziele + \item[6.2] Beispiel: Zahlen und Buchstaben + \item[6.3] Unions + \color{medgreen} + \item[6.4] Virtuelle Methoden + \item[6.5] Beispiel: Graphische Benutzeroberfläche (GUI) + \item[6.6] Ausblick: C++ + \end{itemize} + \item[\textbf{7}] \textbf{Datenstrukturen} + \vspace*{-1cm} + \end{itemize} + +\end{frame} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \item[\textbf{7}] \textbf{Datenstrukturen} + \begin{itemize} + \color{red} + \item[7.1] Stack und FIFO + \item[7.2] Verkettete Listen + \item[7.3] Bäume + \end{itemize} + \vspace*{-1cm} + \end{itemize} + +\end{frame} + +\section{Datenstrukturen} +\subsection{Stack und FIFO} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{minipage}{0.48\textwidth} + Im letzten Praktikumsversuch: + \begin{itemize} + \item + Array nur zum Teil benutzt + \item + Variable speichert genutzte Länge + \item + Elemente hinten anfügen\\ + oder entfernen + \arrowitem + Stack\\ + \strut + \end{itemize} + \bigskip + \begin{itemize} + \item + hinten anfügen/entfernen: $\mathcal{O}(1)$\hspace*{-1cm} + \item + vorne oder in der Mitte einfügen/entfernen: $\mathcal{O}(n)$ + \end{itemize} + \end{minipage}\hfill + \begin{minipage}{0.52\textwidth} + Auch möglich: + \begin{itemize} + \item + Array nur zum Teil benutzt + \item + 2 Variable speichern\\genutzte Länge (ringförmig) + \item + Elemente hinten anfügen\\ + oder vorne entfernen + \arrowitem + FIFO + \end{itemize} + \bigskip + \begin{itemize} + \item + vorne oder hinten\\ + anfügen oder entfernen: $\mathcal{O}(1)$ + \item + in der Mitte einfügen/entfernen: $\mathcal{O}(n)$ + \end{itemize} + \end{minipage}\hspace*{-1.5mm} + +\end{frame} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \bigskip + + \begin{minipage}[b]{6cm} + \begin{center} + "`First In -- First Out"' + + \bigskip + + \begin{picture}(6,4) + \thicklines + \color{structure} + \put(0.5,0){\line(1,0){5}} + + \put(3.5,0){\only<1-5>{\line(0,1){1}}} + \put(4.5,0){\only<1-4>{\line(0,1){1}}} + \put(3.5,1){\only<1-4>{\line(1,0){1}}} + \put(4.0,0.5){\only<1-4>{\makebox(0,0){\lstinline{3}}}} + \put(3.0,1.5){\only<1>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(3.0,1.5){\only<1>{\makebox(0,0)[b]{\lstinline{push (3)}}}} + + \put(2.5,0){\only<2-6>{\line(0,1){1}}} + \put(2.5,1){\only<2-5>{\line(1,0){1}}} + \put(3.0,0.5){\only<2-5>{\makebox(0,0){\lstinline{7}}}} + \put(2.0,1.5){\only<2>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,1.5){\only<2>{\makebox(0,0)[b]{\lstinline{push (7)}}}} + + \put(1.5,0){\only<3-6>{\line(0,1){1}}} + \put(1.5,1){\only<3-6>{\line(1,0){1}}} + \put(2.0,0.5){\only<3-6>{\makebox(0,0){\lstinline{137}}}} + \put(1.0,1.5){\only<3>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(1.0,1.5){\only<3>{\makebox(0,0)[b]{\lstinline{push (137)}}}} + + \put(4.55,1.05){\only<4>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(5.00,1.60){\only<4>{\makebox(0,0)[b]{\lstinline{pop ()}: 3}}} + + \put(3.55,1.05){\only<5>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,1.60){\only<5>{\makebox(0,0)[b]{\lstinline{pop ()}: 7}}} + + \put(2.55,1.05){\only<6>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(3.00,1.60){\only<6>{\makebox(0,0)[b]{\lstinline{pop ()}: 137}}} + \end{picture} + + \bigskip + + FIFO = Queue = Reihe + \end{center} + \end{minipage}\hfill + \begin{minipage}[b]{6cm} + \begin{center} + "`Last In -- First Out"' + + \bigskip + + \begin{picture}(6,4) + \thicklines + \color{structure} + \put(1.5,0){\line(1,0){3}} + + \put(2.5,0){\line(0,1){1}} + \put(3.5,0){\line(0,1){1}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,0.5){\makebox(0,0){\lstinline{3}}} + \put(2.0,1.5){\only<1>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,1.5){\only<1>{\makebox(0,0)[b]{\lstinline{push (3)}}}} + + \put(2.5,1){\only<2-5>{\line(0,1){1}}} + \put(3.5,1){\only<2-5>{\line(0,1){1}}} + \put(2.5,2){\only<2-5>{\line(1,0){1}}} + \put(3.0,1.5){\only<2-5>{\makebox(0,0){\lstinline{7}}}} + \put(2.0,2.5){\only<2>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,2.5){\only<2>{\makebox(0,0)[b]{\lstinline{push (7)}}}} + + \put(2.5,2){\only<3-4>{\line(0,1){1}}} + \put(3.5,2){\only<3-4>{\line(0,1){1}}} + \put(2.5,3){\only<3-4>{\line(1,0){1}}} + \put(3.0,2.5){\only<3-4>{\makebox(0,0){\lstinline{137}}}} + \put(2.0,3.5){\only<3>{\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,-0.45);}}}} + \put(2.0,3.5){\only<3>{\makebox(0,0)[b]{\lstinline{push (137)}}}} + + \put(3.55,3.05){\only<4>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,3.60){\only<4>{\makebox(0,0)[b]{\lstinline{pop ()}: 137}}} + + \put(3.55,2.05){\only<5>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,2.60){\only<5>{\makebox(0,0)[b]{\lstinline{pop ()}: 7}}} + + \put(3.55,1.05){\only<6>{\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.45,0.45);}}}} + \put(4.00,1.60){\only<6>{\makebox(0,0)[b]{\lstinline{pop ()}: 3}}} + \end{picture} + + \bigskip + + LIFO = Stack = Stapel + \end{center} + \end{minipage} + +% +% \dots + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \bigskip + + \begin{minipage}[t]{6cm} + Array (Stack, FIFO):\\ + in der Mitte einfügen + \begin{center} + \begin{picture}(6,3.8) + \thicklines + \color{structure} + \put(1.5,0){\line(1,0){3}} + + \put(2.5,0){\line(0,1){3}} + \put(3.5,0){\line(0,1){3}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,0.5){\makebox(0,0){\lstinline{3}}} + \put(2.5,1){\line(1,0){1}} + \put(3.0,1.5){\makebox(0,0){\lstinline{7}}} + \put(2.5,2){\line(1,0){1}} + \put(3.0,2.5){\makebox(0,0){\lstinline{137}}} + \put(2.5,3){\line(1,0){1}} + + \put(1.5,1.5){\makebox(0,0)[b]{\lstinline{push (5)}}} + \put(1.5,1.45){\makebox(0,0)[tl]{\tikz{\draw[-latex, line width=1pt](0,0)--(0.95,-0.45);}}} + + \put(3.55,2.5){\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)..controls(0.5,0.45)..(0,0.9);}}} + \put(3.55,1.5){\makebox(0,0)[bl]{\tikz{\draw[-latex, line width=1pt](0,0)..controls(0.5,0.45)..(0,0.9);}}} + + \pause + \color{red} + \put(4.1,3.0){\makebox(0,0)[l]{\textbf{1.}}} + \put(4.1,2.0){\makebox(0,0)[l]{\textbf{2.}}} + \put(1.5,1.9){\makebox(0,0)[b]{\textbf{3.}}} + + \pause + \put(6.0,1.5){\makebox(0,0)[tl]{$\mathcal{O}(n)$}} + \put(5.95,1.45){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-1.3,0.4);}}} + \put(5.95,1.49){\makebox(0,0)[br]{\tikz{\draw[-latex](0,0)--(-1.3,1.1);}}} + \end{picture} + \end{center} + \end{minipage}\pause\hfill + \begin{minipage}[t]{5cm} + In Array (Stack, FIFO) \dots + \begin{itemize} + \item + einfügen: $\mathcal{O}(n)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage} + +\end{frame} + +\subsection{Verkettete Listen} + +\begin{frame} + + \showsection + \showsubsection + + \begin{tikzpicture} + \color{structure} + \node(first) at (0,0.5) {first}; + \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3}; + \node[shape=rectangle,draw,line width=1pt](5) at (2,1) {5}; + \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7}; + \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137}; + \node(NULL) at (7,2) {NULL}; + \draw[-latex](first)--(3); + \only<1>{\draw[-latex](3)--(7);} + \only<2>{\draw[-latex](3) to[out=0] (5);} + \only<2>{\draw[-latex](5) to[in=180] (7);} + \draw[-latex](7)--(137); + \draw[-latex](137)--(NULL); + \end{tikzpicture} + \begin{itemize} + \item + Jeder Datensatz enthält einen Zeiger auf das nächste Element. + \item + Beim letzten Element zeigt der Zeiger auf \lstinline{NULL}. + \item + Eine Variable zeigt auf das erste Element. + \item + Wenn die Liste leer ist, zeigt die Variable auf \lstinline{NULL}. + \arrowitem + (einfach) \textbf{verkettete Liste} + \end{itemize} + +\end{frame} + +\begin{frame} + + \showsection + \showsubsection + + \begin{minipage}[t]{5cm} + In Array (Stack, FIFO) \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(n)$ + \item + wahlfreier Zugriff: $\mathcal{O}(1)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage}\hfill + \begin{minipage}[t]{6cm} + In (einfach) verkettete/r Liste \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(1)$ + \item + wahlfreier Zugriff: $\mathcal{O}(n)$ + \item + suchen: $\mathcal{O}(n)$ + \item + geschickt \hspace*{-1.7cm}\tikz{\draw[red](-1.7,0)--(0,0.2);\draw[red](-1.7,0.2)--(0,0);} + suchen: {\color{red}$\mathcal{O}(n)$} + \item + beim Einfügen sortieren: + $\mathcal{O}(n \log n)$ \hspace*{-1.8cm}\tikz{\draw[red](-1.8,0)--(0,0.2);\draw[red](-1.8,0.2)--(0,0);} + $\mathcal{O}(n^2)$ + \end{itemize} + \end{minipage} + \pause + \medskip + \begin{center} + \begin{minipage}[t]{6cm} + In (ausbalancierten) Bäumen \dots + \begin{itemize} + \item + in der Mitte einfügen: $\mathcal{O}(\log n)$ + \item + wahlfreier Zugriff: $\mathcal{O}(\log n)$ + \item + suchen: $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren: + $\mathcal{O}(n \log n)$ + \end{itemize} + \end{minipage} + \end{center} + \vspace*{-1cm} + +\end{frame} + +\subsection{Bäume} + +\begin{frame}[fragile] + + \showsection + \showsubsection + + \begin{minipage}[t]{5cm} + \vspace*{-6cm} + \begin{lstlisting}[gobble=6] + ¡typedef struct node + { + int content; + struct node *left, *right; + } node;¿ + \end{lstlisting} +% \bigskip + \bigskip + \begin{onlyenv}<6-> + \begin{itemize} + \item + Einfügen: rekursiv, $\mathcal{O}(\log n)$ + \item + Suchen: rekursiv, $\mathcal{O}(\log n)$ + \item + beim Einfügen sortieren:\\ + rekursiv, $\mathcal{O}(n\log n)$ + \begin{onlyenv}<7-> + \smallskip + \item + {\color{red} + \emph{Worst Case\/}: $\mathcal{O}(n^2)$\\ + vorher bereits sortiert}\\ + \textarrow\ balancierte Bäume\\ + \hspace*{2.15em}Anwendung: Datenbanken\hspace*{-2cm} + \end{onlyenv} + \end{itemize} + \vspace*{-1cm} + \end{onlyenv} + \end{minipage}\hfill + \begin{minipage}[t]{7cm} + \begin{center} + \begin{tikzpicture} + \color{structure} + \node(root) at (0,0) {\lstinline{node *root;}}; + \begin{onlyenv}<2> + \node(3) at (-2,-3) {\lstinline{NULL}}; + \node(137) at (2,-3) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<2-> + \node[shape=rectangle,draw,line width=1pt](7) at (0,-1.5) {7}; + \draw[-latex](root)--(7); + \draw[-latex](7)--(3); + \draw[-latex](7)--(137); + \end{onlyenv} + \begin{onlyenv}<3> + \node(3) at (-2,-3) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<3-> + \node[shape=rectangle,draw,line width=1pt](137) at (2,-3) {137}; + \node(137_left) at (1,-4.5) {\lstinline{NULL}}; + \node(137_right) at (3,-4.5) {\lstinline{NULL}}; + \draw[-latex](137)--(137_left); + \draw[-latex](137)--(137_right); + \end{onlyenv} + \begin{onlyenv}<4> + \node(5) at (-1,-4.5) {\lstinline{NULL}}; + \end{onlyenv} + \begin{onlyenv}<4-> + \node[shape=rectangle,draw,line width=1pt](3) at (-2,-3) {3}; + \node(3_left) at (-3,-4.5) {\lstinline{NULL}}; + \draw[-latex](3)--(3_left); + \draw[-latex](3)--(5); + \end{onlyenv} + \begin{onlyenv}<5-> + \node[shape=rectangle,draw,line width=1pt](5) at (-1,-4.5) {5}; + \node(5_left) at (-2,-6) {\lstinline{NULL}}; + \node(5_right) at (0,-6) {\lstinline{NULL}}; + \draw[-latex](5)--(5_left); + \draw[-latex](5)--(5_right); + \end{onlyenv} + \end{tikzpicture} + \end{center} + \end{minipage} + +\end{frame} + +\nosectionnonumber{\inserttitle} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \item[\textbf{7}] \textbf{Datenstrukturen} + \begin{itemize} + \color{medgreen} + \item[7.1] Stack und FIFO + \item[7.2] Verkettete Listen + \item[7.3] Bäume + \end{itemize} + \end{itemize} + +\end{frame} + +\begin{frame} + + \shownosectionnonumber + + \begin{itemize} + \item[\textbf{1}] \textbf{Einführung} + \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}} + \item[\textbf{2}] \textbf{Einführung in C} + \item[\textbf{3}] \textbf{Bibliotheken} + \item[\textbf{4}] \textbf{Algorithmen} + \item[\textbf{5}] \textbf{Hardwarenahe Programmierung} + \item[\textbf{6}] \textbf{Objektorientierte Programmierung} + \item[\textbf{7}] \textbf{Datenstrukturen} + \begin{itemize} + \item[7.1] Stack und FIFO + \item[7.2] Verkettete Listen + \item[7.3] Bäume + \end{itemize} + \end{itemize} + + \begin{flushright} + \large\bf\em\color{medgreen}Vielen Dank für Ihre Aufmerksamkeit\\ + und viel Erfolg bei den Prüfungen! + \end{flushright} + +\end{frame} + +\end{document} diff --git a/20210211/hp-musterloesung-20210211.pdf b/20210211/hp-musterloesung-20210211.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c34d9660f17fa4f688a28aab298f6b1ab4e1c9eb Binary files /dev/null and b/20210211/hp-musterloesung-20210211.pdf differ diff --git a/20210211/hp-musterloesung-20210211.tex b/20210211/hp-musterloesung-20210211.tex new file mode 100644 index 0000000000000000000000000000000000000000..58410acb8c778d8cab4ee54bb940bcfedf06ee49 --- /dev/null +++ b/20210211/hp-musterloesung-20210211.tex @@ -0,0 +1,604 @@ +% hp-musterloesung-20210211.pdf - Solutions to the Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Stack-Operationen, einfach und doppelt verkettete Listen, ternärer Baum + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{tikz} + +\begin{document} + + \section*{Hardwarenahe Programmierung\\ + Musterlösung zu den Übungsaufgaben -- 11.\ Februar 2021} + + \exercise{Stack-Operationen} + + Das folgende Programm (\gitfile{hp}{2020ws/20210211}{aufgabe-1.c}) + implementiert einen Stapelspeicher (Stack). + Dies ist ein Array, das nur bis zu einer variablen Obergrenze (Stack-Pointer) + tatsächlich genutzt wird. + An dieser Obergrenze kann man Elemente hinzufügen (push). + + In dieser Aufgabe sollen zusätzlich Elemente + in der Mitte eingefügt werden (insert). + Die dafür bereits existierenden Funktionen \lstinline{insert()} + und \lstinline{insert_sorted()} sind jedoch fehlerhaft. + + \begin{minipage}[t]{0.5\textwidth} + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + #define STACK_SIZE 10 + + int stack[STACK_SIZE]; + int stack_pointer = 0; + + void push (int x) + { + stack[stack_pointer++] = x; + } + + void show (void) + { + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); + } + \end{lstlisting} + \end{minipage}\hfill + \begin{minipage}[t]{0.5\textwidth} + \begin{lstlisting}[gobble=6] + void insert (int x, int pos) + { + for (int i = pos; i < stack_pointer; i++) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; + } + + void insert_sorted (int x) + { + int i = 0; + while (i < stack_pointer && x < stack[i]) + i++; + insert (x, i); + } + + int main (void) + { + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; + } + \end{lstlisting} + \end{minipage} + + \begin{enumerate}[\quad(a)] + \item + Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert()} ihren Parameter \lstinline{x} + an der Stelle \lstinline{pos} in den Stack einfügt + und den sonstigen Inhalt des Stacks verschiebt, aber nicht zerstört. + \points{3} + \item + Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert_sorted()} ihren Parameter \lstinline{x} + an derjenigen Stelle einfügt, an die er von der Sortierung her gehört. + (Der Stack wird hierbei vor dem Funktionsaufruf als sortiert vorausgesetzt.) + \points{2} + \item + Schreiben Sie eine zusätzliche Funktion \lstinline{int search (int x)}, + die die Position (Index) des Elements \lstinline{x} + innerhalb des Stack zurückgibt -- oder die Zahl + \lstinline{-1}, wenn \lstinline{x} nicht im Stack enthalten ist. + Der Rechenaufwand darf höchstens $\mathcal{O}(n)$ betragen. + \points{3} + \item + Wie (c), aber der Rechenaufwand darf höchstens $\mathcal{O}(\log n)$ betragen. + \points{4} + \end{enumerate} + + \goodbreak + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert()} ihren Parameter \lstinline{x} + an der Stelle \lstinline{pos} in den Stack einfügt, + und den sonstigen Inhalt des Stacks verschiebt, aber nicht zerstört.} + + Die \lstinline{for}-Schleife in der Funktion \lstinline{insert()} + durchläuft das Array von unten nach oben. + Um den Inhalt des Arrays von unten nach oben zu verschieben, + muß man die Schleife jedoch von oben nach unten durchlaufen. + + \goodbreak + Um die Funktion zu reparieren, ersetze man also + \begin{lstlisting}[gobble=8] + for (int i = pos; i < stack_pointer; i++) + \end{lstlisting} + durch: + \begin{lstlisting}[gobble=8] + for (int i = stack_pointer - 1; i >= pos; i--) + \end{lstlisting} + (Siehe auch: \gitfile{hp}{2020ws/20210211}{loesung-1.c}) + + \item + \textbf{Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert_sorted()} ihren Parameter \lstinline{x} + an derjenigen Stelle einfügt, an die er von der Sortierung her gehört. + (Der Stack wird hierbei vor dem Funktionsaufruf als sortiert vorausgesetzt.)} + + Der Vergleich \lstinline{x < stack[i]} + als Bestandteil der \lstinline{while}-Bedingung + paßt nicht zur Durchlaufrichtung der Schleife (von unten nach oben). + + Um die Funktion zu reparieren, kann man daher entweder + das Kleinerzeichen durch ein Größerzeichen ersetzen + (\lstinline{x > stack[i]} -- siehe \gitfile{hp}{2020ws/20210211}{loesung-1b-1.c}) + oder die Schleife von oben nach unten durchlaufen + (siehe \gitfile{hp}{2020ws/20210211}{loesung-1b-2.c}). + + Eine weitere Möglichkeit besteht darin, + das Suchen nach der Einfügeposition + mit dem Verschieben des Arrays zu kombinieren + (siehe \gitfile{hp}{2020ws/20210211}{loesung-1.c}). + Hierdurch spart man sich eine Schleife; das Programm wird schneller. + (Es bleibt allerdings bei $\mathcal{O}(n)$.) + + \item + \textbf{Schreiben Sie eine zusätzliche Funktion \lstinline{int search (int x)}, + die die Position (Index) des Elements \lstinline{x} + innerhalb des Stack zurückgibt + -- oder \lstinline{-1}, wenn \lstinline{x} nicht im Stack enthalten ist. + Der Rechenaufwand darf höchstens $\mathcal{O}(n)$ betragen.} + + Man geht in einer Schleife den Stack (= den genutzten Teil des Arrays) durch. + Bei Gleichheit gibt man direkt mit \lstinline{return} den Index zurück. + Nach dem Schleifendurchlauf steht fest, + daß \lstinline{x} nicht im Stack vorhanden ist; + man kann dann direkt \lstinline{-1} zurückgeben + (siehe \gitfile{hp}{2020ws/20210211}{loesung-1c.c}). + + Da es sich um eine einzelne Schleife handelt, + ist die Ordnung $\mathcal{O}(n)$. + + \item + \textbf{Wie (c), aber der Rechenaufwand darf höchstens $\mathcal{O}(\log n)$ betragen.} + + Um $\mathcal{O}(\log n)$ zu erreichen, + halbiert man fortwährend das Intervall von (einschließlich) \lstinline{0} + bis (ausschließlich) \lstinline{stack_pointer} + (siehe \gitfile{hp}{2020ws/20210211}{loesung-1d.c}) -- + wie in der Funktion \lstinline{push_sorted()} + im Beispiel-Programm \gitfile{hp}{2020ws/20210211}{stack-11.c}. + + Ein wichtiger Unterschied besteht darin, + daß man nach dem Durchlauf der Schleife noch auf die Gleichheit + \lstinline{x == stack[left]} (insbesondere nicht: \lstinline{stack[right]}) + prüfen und ggf.\ \lstinline{left} bzw.\ \lstinline{-1} zurückgeben muß. + \end{enumerate} + + \goodbreak + + \exercise{Einfach und doppelt verkettete Listen} + + Das Beispiel-Programm \gitfile{hp}{2020ws/20210211}{aufgabe-2.c} + demonstriert zwei Funktionen zur Verwaltung einfach verketteter Listen: + \lstinline{output_list()} zum Ausgeben der Liste auf den Bildschirm und + \lstinline{insert_into_list()} zum Einfügen in die Liste. + + \begin{enumerate}[\quad(a)] + \item + Ergänzen Sie eine Funktion \lstinline{delete_from_list()} + zum Löschen eines Elements aus der Liste + mit Freigabe des Speicherplatzes. + \points{5} + \item + Ergänzen Sie eine Funktion \lstinline{reverse_list()} + die die Reihenfolge der Elemente in der Liste umdreht.\\ + \points{3} + \end{enumerate} + + Eine doppelt verkettete Liste hat in jedem Knotenpunkt (\lstinline{node}) + \emph{zwei\/} Zeiger -- einen auf das nächste Element (\lstinline{next}) + und einen auf das vorherige Element (z.\,B.\ \lstinline{prev} für "`previous"'). + Dadurch ist es leichter als bei einer einfach verketteten Liste, + die Liste in umgekehrter Reihenfolge durchzugehen. + + \begin{quote} + \begin{tikzpicture} + \color{blendedblue} + \node(first) at (0,3.5) {first}; + \node(NULL1) at (-1,1.25) {NULL}; + \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3}; + \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7}; + \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137}; + \node(NULL2) at (7,2.75) {NULL}; + \draw[-latex](first)--(3); + \draw[-latex](3) to[out=45,in=135] (7); + \draw[-latex](3) to[out=-135,in=0] (NULL1); + \draw[-latex](7) to[out=-135,in=-45] (3); + \draw[-latex](7) to[out=45,in=135] (137); + \draw[-latex](137) to[out=-135,in=-45] (7); + \draw[-latex](137) to[out=45,in=180] (NULL2); + \end{tikzpicture} + \end{quote} + + Der Rückwärts-Zeiger (\lstinline{prev}) des ersten Elements zeigt, + genau wie der Vorwärts-Zeiger (\lstinline{next}) des letzten Elements, + auf \emph{nichts}, hat also den Wert \lstinline{NULL}. + + \begin{enumerate}[\quad(a)]\setcounter{enumi}{2} + \item + Schreiben Sie das Programm um für doppelt verkettete Listen. + \points{5} + \end{enumerate} + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Ergänzen Sie eine Funktion \lstinline{delete_from_list()} + zum Löschen eines Elements aus der Liste + mit Freigabe des Speicherplatzes.} + + Siehe: \gitfile{hp}{2020ws/20210211}{loesung-2a.c} + + Um ein Element aus einer verketteten Liste zu löschen, + müssen zuerst die Zeiger umgestellt werden, + um das Element von der Liste auszuschließen. + Erst danach darf der Speicherplatz für das Element freigegeben werden. + +% Da das Beispielprogramm (\gitfile{hp}{2020ws/20210211}{lists-5.c}) +% nicht mit dynamischem Speicher arbeitet, +% stellen wir dieses zunächst auf dynamischen Speicher um, z.\,B.: +% \begin{lstlisting}[gobble=8] +% node *element5 = malloc (sizeof (node)); +% \end{lstlisting} +% Danach bezeichnet \lstinline{element5} +% die Adresse der \lstinline{struct}-Variablen; +% es wird also \lstinline{element5} an die Funktionen übergeben +% und nicht \lstinline{&element5} (die Adresse des Zeigers). + +% Um nun ein Element aus der Liste zu entfernen, +% benötigt man + Man benötigt also + \emph{das vorherige Element}, + dessen \lstinline{next}-Zeiger man dann auf + das übernächste Element \lstinline{next->next} weitersetzt. + + Bei jedem Zeiger muß man vor dem Zugriff prüfen, + daß dieser nicht auf \lstinline{NULL} zeigt. + (Die Musterlösung ist in dieser Hinsicht nicht konsequent. + Für den Produktiveinsatz müßte z.\,B.\ \lstinline{delete_from_list()} + auch den übergebenen Zeiger \lstinline{what} auf \lstinline{NULL} prüfen.) + + Ein Spezialfall tritt ein, wenn das erste Element einer Liste + entfernt werden soll. In diesem Fall tritt \lstinline{first} + an die Stelle des \lstinline{next}-Zeigers + des (nicht vorhandenen) vorherigen Elements. + Da \lstinline{delete_from_list()} \emph{schreibend\/} auf \lstinline{first} + zugreift, muß \lstinline{first} \emph{als Zeiger\/} übergeben werden + (\lstinline{node **first}). + + Um alle Spezialfälle zu testen (am Anfang, am Ende und in der Mitte der Liste), + wurden die Testfälle im Hauptprogramm erweitert. + + \item + \textbf{Schreiben Sie das Programm um für doppelt verkettete Listen.} + + Siehe: \gitfile{hp}{2020ws/20210211}{loesung-2b.c} + + Bei allen Einfüge- und Löschaktionen müssen \emph{jeweils zwei\/} + \lstinline{next}- und \lstinline{prev}-Zeiger neu gesetzt werden. + + Zum Debuggen empfiehlt es sich sehr, + eine Funktion zu schreiben, die die Liste auf Konsistenz prüft + (hier: \lstinline{check_list()}). + + Das Testprogramm macht von der Eigenschaft der doppelt verketteten Liste, + daß man sie auch rückwärts effizient durchgehen kann, keinen Gebrauch. + Um diese Eigenschaft als Vorteil nutzen zu können, empfiehlt es sich, + zusätzlich zu \lstinline{first} + auch einen Zeiger auf das letzte Element (z.\,B.\ \lstinline{last}) + einzuführen. Dieser muß dann natürlich bei allen Operationen + (Einfügen, Löschen, \dots) auf dem aktuellen Stand gehalten werden. + + \end{enumerate} + + \exercise{Ternärer Baum} + + Der in der Vorlesung vorgestellte \newterm{binäre Baum\/} + ist nur ein Spezialfall; + im allgemeinen können Bäume auch mehr als zwei Verzweigungen + pro Knotenpunkt haben. + Dies ist nützlich bei der Konstruktion \emph{balancierter Bäume}, + also solcher, die auch im \emph{Worst Case\/} + nicht zu einer linearen Liste entarten, + sondern stets eine -- möglichst flache -- Baumstruktur behalten. + + Wir betrachten einen Baum mit bis zu drei Verzweigungen pro Knotenpunkt, + einen sog.\ \newterm{ternären Baum}. + Jeder Knoten enthält dann nicht nur einen, + sondern \emph{zwei\/} Werte als Inhalt: + + \begin{lstlisting} + typedef struct node + { + int content_left, content_right; + struct node *left, *middle, *right; + } node; + \end{lstlisting} + + Wir konstruieren nun einen Baum nach folgenden Regeln: + \vspace{-\medskipamount} + \begin{itemize}\itemsep0pt + \item + Innerhalb eines Knotens sind die Werte sortiert: + \lstinline{content_left} muß stets kleiner sein als \lstinline{content_right}. + \item + Der Zeiger \lstinline{left} zeigt auf Knoten, + deren enthaltene Werte durchweg kleiner sind als \lstinline{content_left}. + \item + Der Zeiger \lstinline{right} zeigt auf Knoten, + deren enthaltene Werte durchweg größer sind als \lstinline{content_right}. + \item + Der Zeiger \lstinline{middle} zeigt auf Knoten, + deren enthaltene Werte durchweg größer sind als \lstinline{content_left}, + aber kleiner als \lstinline{content_right}. + \item + Ein Knoten muß nicht immer mit zwei Werten voll besetzt sein; + er darf auch \emph{nur einen\/} gültigen Wert enthalten. + + Der Einfachheit halber lassen wir in diesem Beispiel + nur positive Zahlen als Werte zu. + Wenn ein Knoten nur einen Wert enthält, + setzen wir \lstinline{content_right = -1}, + und der Zeiger \lstinline{middle} wird nicht verwendet. + \item + Wenn wir neue Werte in den Baum einfügen, + werden \emph{zuerst\/} die nicht voll besetzten Knoten aufgefüllt + und \emph{danach erst\/} neue Knoten angelegt und Zeiger gesetzt. + \item + Beim Auffüllen eines Knotens darf nötigenfalls \lstinline{content_left} + nach \lstinline{content_right} verschoben werden. + Ansonsten werden einmal angelegte Knoten nicht mehr verändert. + \end{itemize} + \vspace*{-\medskipamount} + (In der Praxis dürfen Knoten gemäß speziellen Regeln + nachträglich verändert werden, + um Entartungen gar nicht erst entstehen zu lassen -- + siehe z.\,B.\ \url{https://de.wikipedia.org/wiki/2-3-4-Baum}.) + + \begin{enumerate}[\quad(a)] + \item + Zeichnen Sie ein Schaubild, das veranschaulicht, + wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12 + nacheinander und in dieser Reihenfolge + in den oben beschriebenen Baum eingefügt werden + -- analog zu den Vortragsfolien (\gitfile{hp}{2020ws/20210211}{hp-20210211.pdf}), + Seite 42. + \points{3} + % + % Lösung: + % + % 7 137 + % / | + % 3 5 12 42 + % / \ + % 1 2 6 + % + % (NULL-Zeiger sind hier nicht dargestellt, + % gehören aber dazu.) + % + \goodbreak + \item + Dasselbe, aber in der Reihenfolge + 2, 7, 42, 12, 1, 137, 5, 6, 3. + \points{3} + % + % Lösung: + % + % 2 7 + % / | \ + % 1 5 6 12 42 + % / \ + % 3 137 + % + % (NULL-Zeiger sind hier wieder nicht dargestellt, + % gehören aber dazu.) + % + \item + Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment, + wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum + sortiert auszugeben. + \points{4} + \end{enumerate} + + \solution + + \begin{enumerate}[\quad(a)] + \item + \textbf{Zeichnen Sie ein Schaubild, das veranschaulicht, + wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12 + nacheinander und in dieser Reihenfolge + in den oben beschriebenen Baum eingefügt werden + -- analog zu den Vortragsfolien (\gitfile{hp}{2020ws/20210211}{hp-20190121.pdf}), + Seite 21.} + % + % Lösung: + % + % 7 137 + % / | + % 3 5 12 42 + % / \ + % 1 2 6 + % + % (NULL-Zeiger sind hier nicht dargestellt, + % gehören aber dazu.) + % + \begin{center} + \newcommand{\x}{~\makebox(0,0){\raisebox{0.7em}{\rule{1pt}{1.4em}}}~} + \begin{tikzpicture} + \color{blendedblue} + \node(root) at (0,0) {\lstinline{node *root;}}; + \node[shape=rectangle,draw,line width=1pt](7-137) at (0,-1.5) {7\x 137}; + \draw[-latex](root)--(7-137); + \node[shape=rectangle,draw,line width=1pt](3-5) at (-2,-3) {3\x 5}; + \draw[-latex](7-137)--(3-5); + \node[shape=rectangle,draw,line width=1pt](12-42) at (0,-3) {12\x 42}; + \draw[-latex](7-137)--(12-42); + \node[shape=rectangle,draw,line width=1pt](1-2) at (-4,-4.5) {1\x 2}; + \draw[-latex](3-5)--(1-2); + \node[shape=rectangle,draw,line width=1pt](6) at (0,-4.5) {6}; + \draw[-latex](3-5)--(6); + \end{tikzpicture} + \end{center} + Bemerkungen: + \begin{itemize} + \item + Zeiger mit dem Wert \lstinline{NULL} sind nicht dargestellt: + \lstinline{right}-Zeiger von 7/137, + \lstinline{middle}-Zeiger von 3/5, + sämtliche Zeiger von 1/2, 12/42 und 6. + \item + Beim Einfügen der 12 wird die sich bereits vorher in diesem + \lstinline{node} befindliche 42 zu \lstinline{content_right}, + und die 12 wird das neue \lstinline{content_left}. + \item + Dieser Baum hat sehr einfache Regeln und ist daher \emph{nicht\/} + balanciert. Insbesondere unsere Regel, daß einmal angelegte Knoten + nicht mehr verändert werden dürfen, steht dem im Wege. + Ein einfaches Beispiel für einen \emph{balancierten\/} ternären + Baum ist der 2-3-Baum -- siehe z.\,B.\ \url{https://en.wikipedia.org/wiki/2-3_tree}. + \end{itemize} + \goodbreak + \item + \textbf{Dasselbe, aber in der Reihenfolge + 2, 7, 42, 12, 1, 137, 5, 6, 3.} + % + % Lösung: + % + % 2 7 + % / | \ + % 1 5 6 12 42 + % / \ + % 3 137 + % + % (NULL-Zeiger sind hier wieder nicht dargestellt, + % gehören aber dazu.) + % + \begin{center} + \newcommand{\x}{~\makebox(0,0){\raisebox{0.7em}{\rule{1pt}{1.4em}}}~} + \begin{tikzpicture} + \color{blendedblue} + \node(root) at (0,0) {\lstinline{node *root;}}; + \node[shape=rectangle,draw,line width=1pt](2-7) at (0,-1.5) {2\x 7}; + \draw[-latex](root)--(7-137); + \node[shape=rectangle,draw,line width=1pt](1) at (-2,-3) {1}; + \draw[-latex](2-7)--(1); + \node[shape=rectangle,draw,line width=1pt](5-6) at (0,-3) {5\x 6}; + \draw[-latex](2-7)--(5-6); + \node[shape=rectangle,draw,line width=1pt](3) at (-2,-4.5) {3}; + \draw[-latex](5-6)--(3); + \node[shape=rectangle,draw,line width=1pt](12-42) at (2,-3) {12\x 42}; + \draw[-latex](2-7)--(12-42); + \node[shape=rectangle,draw,line width=1pt](137) at (4,-4.5) {137}; + \draw[-latex](12-42)--(137); + \end{tikzpicture} + \end{center} + Bemerkungen: + \begin{itemize} + \item + Wieder sind Zeiger mit dem Wert \lstinline{NULL} nicht dargestellt: + \lstinline{middle}- und \lstinline{right}-Zeiger von 5/6, + \lstinline{left}- und \lstinline{middle}-Zeiger von 12/42, + sämtliche Zeiger von 1, 3 und 137. + \item + Beim Einfügen der 12 wird wieder die sich bereits vorher in diesem + \lstinline{node} befindliche 42 zu \lstinline{content_right}, + und die 12 wird das neue \lstinline{content_left}. + \end{itemize} + \item + \textbf{Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment, + wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum + sortiert auszugeben.} + + Die entscheidende Idee ist \textbf{Rekursion}. + + Eine Funktion, die den gesamten Baum ausgibt, + müßte einmalig für den Zeiger \lstinline{root} aufgerufen werden + und folgendes tun: + \begin{enumerate}[\quad 1.] + \item + falls der übergebene Zeiger den Wert \lstinline{NULL} hat, + nichts ausgeben, sondern die Funktion direkt beenden, + \item + sich selbst für den \lstinline{left}-Zeiger aufrufen, + \item + den Wert von \lstinline{content_left} ausgeben, + \item + sich selbst für den \lstinline{middle}-Zeiger aufrufen, + \item + sofern vorhanden (also ungleich \lstinline{-1}), + den Wert von \lstinline{content_right} ausgeben, + \item + sich selbst für den \lstinline{right}-Zeiger aufrufen. + \end{enumerate} + Als C-Fragment: + \begin{lstlisting}[gobble=8] + void output_tree (node *root) + { + if (root) + { + output_tree (root->left); + printf ("%d\n", root->content_left); + output_tree (root->middle); + if (root->content_right >= 0) + printf ("%d\n", root->content_right); + output_tree (root->right); + } + } + \end{lstlisting} + Die Datei \gitfile{hp}{2020ws/20210211}{loesung-3c.c} erweitert dieses Fragment + zu einem vollständigen C-Programm zum Erstellen und sortierten Ausgeben + eines ternären Baums mit den Zahlenwerten von Aufgabenteil (a). + \end{enumerate} + +\end{document} diff --git a/20210211/hp-uebung-20210211.pdf b/20210211/hp-uebung-20210211.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0aa790eccab2acdd2ee60d0f2d7465210f940d2d Binary files /dev/null and b/20210211/hp-uebung-20210211.pdf differ diff --git a/20210211/hp-uebung-20210211.tex b/20210211/hp-uebung-20210211.tex new file mode 100644 index 0000000000000000000000000000000000000000..c85a746705e45e48ba4c973d4a4259934c029f1d --- /dev/null +++ b/20210211/hp-uebung-20210211.tex @@ -0,0 +1,313 @@ +% hp-uebung-20210204.pdf - Exercises on Low-Level Programming +% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Peter Gerwinski +% +% This document is free software: you can redistribute it and/or +% modify it either under the terms of the Creative Commons +% Attribution-ShareAlike 3.0 License, or under the terms of the +% GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) +% any later version. +% +% This document is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this document. If not, see <http://www.gnu.org/licenses/>. +% +% You should have received a copy of the Creative Commons +% Attribution-ShareAlike 3.0 Unported License along with this +% document. If not, see <http://creativecommons.org/licenses/>. + +% README: Stack-Operationen, einfach und doppelt verkettete Listen, ternärer Baum + +\documentclass[a4paper]{article} + +\usepackage{pgscript} +\usepackage{tikz} + +\begin{document} + +% \thispagestyle{empty} + + \section*{Hardwarenahe Programmierung\\ + Übungsaufgaben -- 11.\ Februar 2021} + +% Diese Übung enthält Punkteangaben wie in einer Klausur. +% Um zu "`bestehen"', müssen Sie innerhalb von 100 Minuten +% unter Verwendung ausschließlich zugelassener Hilfsmittel +% 17 Punkte (von insgesamt \totalpoints) erreichen. + + \exercise{Stack-Operationen} + + Das folgende Programm (\gitfile{hp}{2020ws/20210211}{aufgabe-1.c}) + implementiert einen Stapelspeicher (Stack). + Dies ist ein Array, das nur bis zu einer variablen Obergrenze (Stack-Pointer) + tatsächlich genutzt wird. + An dieser Obergrenze kann man Elemente hinzufügen (push). + + In dieser Aufgabe sollen zusätzlich Elemente + in der Mitte eingefügt werden (insert). + Die dafür bereits existierenden Funktionen \lstinline{insert()} + und \lstinline{insert_sorted()} sind jedoch fehlerhaft. + + \begin{minipage}[t]{0.5\textwidth} + \begin{lstlisting}[gobble=6] + #include <stdio.h> + + #define STACK_SIZE 10 + + int stack[STACK_SIZE]; + int stack_pointer = 0; + + void push (int x) + { + stack[stack_pointer++] = x; + } + + void show (void) + { + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); + } + \end{lstlisting} + \end{minipage}\hfill + \begin{minipage}[t]{0.5\textwidth} + \begin{lstlisting}[gobble=6] + void insert (int x, int pos) + { + for (int i = pos; i < stack_pointer; i++) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; + } + + void insert_sorted (int x) + { + int i = 0; + while (i < stack_pointer && x < stack[i]) + i++; + insert (x, i); + } + + int main (void) + { + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; + } + \end{lstlisting} + \end{minipage} + + \begin{enumerate}[\quad(a)] + \item + Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert()} ihren Parameter \lstinline{x} + an der Stelle \lstinline{pos} in den Stack einfügt + und den sonstigen Inhalt des Stacks verschiebt, aber nicht zerstört. +% \points{3} + \item + Korrigieren Sie das Programm so, + daß die Funktion \lstinline{insert_sorted()} ihren Parameter \lstinline{x} + an derjenigen Stelle einfügt, an die er von der Sortierung her gehört. + (Der Stack wird hierbei vor dem Funktionsaufruf als sortiert vorausgesetzt.) +% \points{2} + \item + Schreiben Sie eine zusätzliche Funktion \lstinline{int search (int x)}, + die die Position (Index) des Elements \lstinline{x} + innerhalb des Stack zurückgibt -- oder die Zahl + \lstinline{-1}, wenn \lstinline{x} nicht im Stack enthalten ist. + Der Rechenaufwand darf höchstens $\mathcal{O}(n)$ betragen. +% \points{3} + \item + Wie (c), aber der Rechenaufwand darf höchstens $\mathcal{O}(\log n)$ betragen. +% \points{4} + \end{enumerate} + + \goodbreak + + \exercise{Einfach und doppelt verkettete Listen} + + Das Beispiel-Programm \gitfile{hp}{2020ws/20210211}{aufgabe-2.c} + demonstriert zwei Funktionen zur Verwaltung einfach verketteter Listen: + \lstinline{output_list()} zum Ausgeben der Liste auf den Bildschirm und + \lstinline{insert_into_list()} zum Einfügen in die Liste. + + \begin{enumerate}[\quad(a)] + \item + Ergänzen Sie eine Funktion \lstinline{delete_from_list()} + zum Löschen eines Elements aus der Liste + mit Freigabe des Speicherplatzes. +% \points{5} + \item + Ergänzen Sie eine Funktion \lstinline{reverse_list()} + die die Reihenfolge der Elemente in der Liste umdreht.\\ +% \points{3} + \end{enumerate} + + Eine doppelt verkettete Liste hat in jedem Knotenpunkt (\lstinline{node}) + \emph{zwei\/} Zeiger -- einen auf das nächste Element (\lstinline{next}) + und einen auf das vorherige Element (z.\,B.\ \lstinline{prev} für "`previous"'). + Dadurch ist es leichter als bei einer einfach verketteten Liste, + die Liste in umgekehrter Reihenfolge durchzugehen. + + \begin{quote} + \begin{tikzpicture} + \color{blendedblue} + \node(first) at (0,3.5) {first}; + \node(NULL1) at (-1,1.25) {NULL}; + \node[shape=rectangle,draw,line width=1pt](3) at (1,2) {3}; + \node[shape=rectangle,draw,line width=1pt](7) at (3,2) {7}; + \node[shape=rectangle,draw,line width=1pt](137) at (5,2) {137}; + \node(NULL2) at (7,2.75) {NULL}; + \draw[-latex](first)--(3); + \draw[-latex](3) to[out=45,in=135] (7); + \draw[-latex](3) to[out=-135,in=0] (NULL1); + \draw[-latex](7) to[out=-135,in=-45] (3); + \draw[-latex](7) to[out=45,in=135] (137); + \draw[-latex](137) to[out=-135,in=-45] (7); + \draw[-latex](137) to[out=45,in=180] (NULL2); + \end{tikzpicture} + \end{quote} + + Der Rückwärts-Zeiger (\lstinline{prev}) des ersten Elements zeigt, + genau wie der Vorwärts-Zeiger (\lstinline{next}) des letzten Elements, + auf \emph{nichts}, hat also den Wert \lstinline{NULL}. + + \begin{enumerate}[\quad(a)]\setcounter{enumi}{2} + \item + Schreiben Sie das Programm um für doppelt verkettete Listen. +% \points{5} + \end{enumerate} + + \exercise{Ternärer Baum} + + Der in der Vorlesung vorgestellte \newterm{binäre Baum\/} + ist nur ein Spezialfall; + im allgemeinen können Bäume auch mehr als zwei Verzweigungen + pro Knotenpunkt haben. + Dies ist nützlich bei der Konstruktion \emph{balancierter Bäume}, + also solcher, die auch im \emph{Worst Case\/} + nicht zu einer linearen Liste entarten, + sondern stets eine -- möglichst flache -- Baumstruktur behalten. + + Wir betrachten einen Baum mit bis zu drei Verzweigungen pro Knotenpunkt, + einen sog.\ \newterm{ternären Baum}. + Jeder Knoten enthält dann nicht nur einen, + sondern \emph{zwei\/} Werte als Inhalt: + + \begin{lstlisting} + typedef struct node + { + int content_left, content_right; + struct node *left, *middle, *right; + } node; + \end{lstlisting} + + Wir konstruieren nun einen Baum nach folgenden Regeln: + \vspace{-\medskipamount} + \begin{itemize}\itemsep0pt + \item + Innerhalb eines Knotens sind die Werte sortiert: + \lstinline{content_left} muß stets kleiner sein als \lstinline{content_right}. + \item + Der Zeiger \lstinline{left} zeigt auf Knoten, + deren enthaltene Werte durchweg kleiner sind als \lstinline{content_left}. + \item + Der Zeiger \lstinline{right} zeigt auf Knoten, + deren enthaltene Werte durchweg größer sind als \lstinline{content_right}. + \item + Der Zeiger \lstinline{middle} zeigt auf Knoten, + deren enthaltene Werte durchweg größer sind als \lstinline{content_left}, + aber kleiner als \lstinline{content_right}. + \item + Ein Knoten muß nicht immer mit zwei Werten voll besetzt sein; + er darf auch \emph{nur einen\/} gültigen Wert enthalten. + + Der Einfachheit halber lassen wir in diesem Beispiel + nur positive Zahlen als Werte zu. + Wenn ein Knoten nur einen Wert enthält, + setzen wir \lstinline{content_right = -1}, + und der Zeiger \lstinline{middle} wird nicht verwendet. + \item + Wenn wir neue Werte in den Baum einfügen, + werden \emph{zuerst\/} die nicht voll besetzten Knoten aufgefüllt + und \emph{danach erst\/} neue Knoten angelegt und Zeiger gesetzt. + \item + Beim Auffüllen eines Knotens darf nötigenfalls \lstinline{content_left} + nach \lstinline{content_right} verschoben werden. + Ansonsten werden einmal angelegte Knoten nicht mehr verändert. + \end{itemize} + \vspace*{-\medskipamount} + (In der Praxis dürfen Knoten gemäß speziellen Regeln + nachträglich verändert werden, + um Entartungen gar nicht erst entstehen zu lassen -- + siehe z.\,B.\ \url{https://de.wikipedia.org/wiki/2-3-4-Baum}.) + + \begin{enumerate}[\quad(a)] + \item + Zeichnen Sie ein Schaubild, das veranschaulicht, + wie die Zahlen 7, 137, 3, 5, 6, 42, 1, 2 und 12 + nacheinander und in dieser Reihenfolge + in den oben beschriebenen Baum eingefügt werden + -- analog zu den Vortragsfolien (\gitfile{hp}{2020ws/20210211}{hp-20210211.pdf}), + Seite 42. +% \points{3} + % + % Lösung: + % + % 7 137 + % / | + % 3 5 12 42 + % / \ + % 1 2 6 + % + % (NULL-Zeiger sind hier nicht dargestellt, + % gehören aber dazu.) + % + \item + Dasselbe, aber in der Reihenfolge + 2, 7, 42, 12, 1, 137, 5, 6, 3. +% \points{3} + % + % Lösung: + % + % 2 7 + % / | \ + % 1 5 6 12 42 + % / \ + % 3 137 + % + % (NULL-Zeiger sind hier wieder nicht dargestellt, + % gehören aber dazu.) + % + \item + Beschreiben Sie in Worten und/oder als C-Quelltext-Fragment, + wie eine Funktion aussehen müßte, um den auf diese Weise entstandenen Baum + sortiert auszugeben. +% \points{4} + \end{enumerate} + + \begin{flushright} + \textit{Viel Erfolg -- auch in den Prüfungen!} + \end{flushright} + +% \makeatletter +% \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}} +% \makeatother + +\end{document} diff --git a/20210211/lists-1.c b/20210211/lists-1.c new file mode 100644 index 0000000000000000000000000000000000000000..a04067e1403601ef56dd706d6148c1d386884e82 --- /dev/null +++ b/20210211/lists-1.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +typedef struct +{ + int content; + node *next; +} node; + +int main (void) +{ + return 0; +} diff --git a/20210211/lists-2.c b/20210211/lists-2.c new file mode 100644 index 0000000000000000000000000000000000000000..f27d1d5af7c0c237f0d0286155380ef9452a497a --- /dev/null +++ b/20210211/lists-2.c @@ -0,0 +1,12 @@ +#include <stdio.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +int main (void) +{ + return 0; +} diff --git a/20210211/lists-3.c b/20210211/lists-3.c new file mode 100644 index 0000000000000000000000000000000000000000..9c9029724efff25263813c5491add92504779d17 --- /dev/null +++ b/20210211/lists-3.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +int main (void) +{ + node node3 = { 3, NULL }; + node node7 = { 7, NULL }; + node node137 = { 137, NULL }; + + node *first = &node3; + + for (node *p = first; p; p = p->next) + printf ("%d\n", p->content); + + return 0; +} diff --git a/20210211/lists-4.c b/20210211/lists-4.c new file mode 100644 index 0000000000000000000000000000000000000000..e048736b85cc228c35f31644d003e00cdefc5496 --- /dev/null +++ b/20210211/lists-4.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +int main (void) +{ + node node3 = { 3, NULL }; + node node7 = { 7, NULL }; + node node137 = { 137, NULL }; + + node3.next = &node7; + node7.next = &node137; + node137.next = NULL; + + node *first = &node3; + + for (node *p = first; p; p = p->next) + printf ("%d\n", p->content); + + return 0; +} diff --git a/20210211/lists-5.c b/20210211/lists-5.c new file mode 100644 index 0000000000000000000000000000000000000000..a0cc620a884c133dd89582de726139091bc9c5d0 --- /dev/null +++ b/20210211/lists-5.c @@ -0,0 +1,29 @@ +#include <stdio.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +int main (void) +{ + node node3 = { 3, NULL }; + node node7 = { 7, NULL }; + node node137 = { 137, NULL }; + + node3.next = &node7; + node7.next = &node137; + node137.next = NULL; + + node node5 = { 5, NULL }; + node5.next = node3.next; + node3.next = &node5; + + node *first = &node3; + + for (node *p = first; p; p = p->next) + printf ("%d\n", p->content); + + return 0; +} diff --git a/20210211/loesung-1.c b/20210211/loesung-1.c new file mode 100644 index 0000000000000000000000000000000000000000..9b87d6c2f977af2843bcc2b75896fb5f00d8fc35 --- /dev/null +++ b/20210211/loesung-1.c @@ -0,0 +1,62 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = stack_pointer - 1; i >= pos; i--) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = stack_pointer - 1; + while (i >= 0 && x < stack[i]) + { + stack[i + 1] = stack[i]; + i--; + } + stack[i + 1] = x; + stack_pointer++; +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; +} diff --git a/20210211/loesung-1b-1.c b/20210211/loesung-1b-1.c new file mode 100644 index 0000000000000000000000000000000000000000..cbbe37055109d203105a7ad4acb63d5bef61f4c0 --- /dev/null +++ b/20210211/loesung-1b-1.c @@ -0,0 +1,58 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = stack_pointer - 1; i >= pos; i--) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = 0; + while (i < stack_pointer && x > stack[i]) + i++; + insert (x, i); +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; +} diff --git a/20210211/loesung-1b-2.c b/20210211/loesung-1b-2.c new file mode 100644 index 0000000000000000000000000000000000000000..b1e1ae846f15a29e9cd53a8d1d689e3ccbefacce --- /dev/null +++ b/20210211/loesung-1b-2.c @@ -0,0 +1,58 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = stack_pointer - 1; i >= pos; i--) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = stack_pointer - 1; + while (i >= 0 && x < stack[i]) + i--; + insert (x, i + 1); +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + return 0; +} diff --git a/20210211/loesung-1c.c b/20210211/loesung-1c.c new file mode 100644 index 0000000000000000000000000000000000000000..79d061e3d7b78a2bec05b632e74b083a16d5a326 --- /dev/null +++ b/20210211/loesung-1c.c @@ -0,0 +1,72 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = stack_pointer - 1; i >= pos; i--) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = stack_pointer - 1; + while (i >= 0 && x < stack[i]) + { + stack[i + 1] = stack[i]; + i--; + } + stack[i + 1] = x; + stack_pointer++; +} + +int search (int x) +{ + for (int i = 0; i < stack_pointer; i++) + if (stack[i] == x) + return i; + return -1; +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + printf ("%d\n", search (42)); + printf ("%d\n", search (1117)); + return 0; +} diff --git a/20210211/loesung-1d.c b/20210211/loesung-1d.c new file mode 100644 index 0000000000000000000000000000000000000000..9079d8d3be7a500498aede2cf8e89a7d7db48a35 --- /dev/null +++ b/20210211/loesung-1d.c @@ -0,0 +1,86 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +void show (void) +{ + printf ("stack content:"); + for (int i = 0; i < stack_pointer; i++) + printf (" %d", stack[i]); + if (stack_pointer) + printf ("\n"); + else + printf (" (empty)\n"); +} + +void insert (int x, int pos) +{ + for (int i = stack_pointer - 1; i >= pos; i--) + stack[i + 1] = stack[i]; + stack[pos] = x; + stack_pointer++; +} + +void insert_sorted (int x) +{ + int i = stack_pointer - 1; + while (i >= 0 && x < stack[i]) + { + stack[i + 1] = stack[i]; + i--; + } + stack[i + 1] = x; + stack_pointer++; +} + +int search (int x) +{ + int left = 0; + int right = stack_pointer; + while (left < right - 1) + { + int middle = (left + right) / 2; + if (x < stack[middle]) + right = middle; + else + left = middle; + } + if (x == stack[left]) + return left; + else + return -1; +} + +int main (void) +{ + push (3); + push (7); + push (137); + show (); + insert (5, 1); + show (); + insert_sorted (42); + show (); + insert_sorted (2); + show (); + printf ("%d\n", search (2)); + printf ("%d\n", search (4)); + printf ("%d\n", search (42)); + printf ("%d\n", search (67)); + printf ("%d\n", search (137)); + printf ("%d\n", search (1117)); + return 0; +} diff --git a/20210211/loesung-2a.c b/20210211/loesung-2a.c new file mode 100644 index 0000000000000000000000000000000000000000..93f5e5629a98d13d6292c56d1a3f855b4f5bd8fd --- /dev/null +++ b/20210211/loesung-2a.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <stdlib.h> + +typedef struct node +{ + int content; + struct node *next; +} node; + +void output_list (node *first) +{ + for (node *p = first; p; p = p->next) + printf ("%d ", p->content); + printf ("\n"); +} + +void insert_into_list (node *what, node *where) +{ + what->next = where->next; + where->next = what; +} + +void delete_from_list (node *what, node **first) +{ + if (what == *first) + *first = what->next; + else + { + node *p = *first; + while (p && p->next != what) + p = p->next; + if (p) + p->next = what->next; + } + free (what); +} + +int main (void) +{ + node *element3 = malloc (sizeof (node)); + node *element7 = malloc (sizeof (node)); + node *element137 = malloc (sizeof (node)); + + element3->content = 3; + element7->content = 7; + element137->content = 137; + + node *first = element3; + element3->next = element7; + element7->next = element137; + element137->next = NULL; + + output_list (first); + + node *element5 = malloc (sizeof (node)); + element5->content = 5; + insert_into_list (element5, element3); + + output_list (first); + + delete_from_list (element5, &first); + output_list (first); + delete_from_list (element3, &first); + output_list (first); + delete_from_list (element137, &first); + output_list (first); + + return 0; +} diff --git a/20210211/loesung-2b.c b/20210211/loesung-2b.c new file mode 100644 index 0000000000000000000000000000000000000000..811b99b1fc9697ca0302eea8950c9bc6e7ab6042 --- /dev/null +++ b/20210211/loesung-2b.c @@ -0,0 +1,97 @@ +#include <stdio.h> +#include <stdlib.h> + +typedef struct node +{ + int content; + struct node *next, *prev; +} node; + +void check_list (node *first) +{ + for (node *p = first; p; p = p->next) + { + if (p->next && p->next->prev != p) + fprintf (stderr, "List inconsistency!\n"); + if (p->prev && p->prev->next != p) + fprintf (stderr, "List inconsistency!\n"); + } +} + +void output_list (node *first) +{ + for (node *p = first; p; p = p->next) + printf ("%d ", p->content); + printf ("\n"); +} + +void insert_into_list (node *what, node *where) +{ + what->next = where->next; + if (where->next) + where->next->prev = what; + what->prev = where; + where->next = what; +} + +void delete_from_list (node *what, node **first) +{ + if (what == *first) + { + *first = what->next; + if (*first) + (*first)->prev = NULL; + } + else + { + node *p = *first; + while (p && p->next != what) + p = p->next; + if (p) + p->next = what->next; + if (what->next) + what->next->prev = p; + } + free (what); +} + +int main (void) +{ + node *element3 = malloc (sizeof (node)); + node *element7 = malloc (sizeof (node)); + node *element137 = malloc (sizeof (node)); + + element3->content = 3; + element7->content = 7; + element137->content = 137; + + node *first = element3; + element3->prev = NULL; + element3->next = element7; + element7->prev = element3; + element7->next = element137; + element137->prev = element7; + element137->next = NULL; + + output_list (first); + check_list (first); + + node *element5 = malloc (sizeof (node)); + element5->content = 5; + insert_into_list (element5, element3); + + output_list (first); + check_list (first); + + delete_from_list (element5, &first); + output_list (first); + check_list (first); + delete_from_list (element3, &first); + output_list (first); + check_list (first); + delete_from_list (element137, &first); + output_list (first); + check_list (first); + + return 0; +} diff --git a/20210211/loesung-3c.c b/20210211/loesung-3c.c new file mode 100644 index 0000000000000000000000000000000000000000..a6dea990b25895475e343f07895c6a946426d2d8 --- /dev/null +++ b/20210211/loesung-3c.c @@ -0,0 +1,68 @@ +#include <stdio.h> +#include <stdlib.h> + +typedef struct node +{ + int content_left, content_right; + struct node *left, *middle, *right; +} node; + +void insert_into_tree (node **root, int value) +{ + if (*root) + { + if ((*root)->content_right >= 0) + if (value < (*root)->content_left) + insert_into_tree (&(*root)->left, value); + else if (value < (*root)->content_right) + insert_into_tree (&(*root)->middle, value); + else + insert_into_tree (&(*root)->right, value); + else + if (value < (*root)->content_left) + { + (*root)->content_right = (*root)->content_left; + (*root)->content_left = value; + } + else + (*root)->content_right = value; + } + else + { + *root = malloc (sizeof (node)); + (*root)->left = NULL; + (*root)->content_left = value; + (*root)->middle = NULL; + (*root)->content_right = -1; + (*root)->right = NULL; + } +} + +void output_tree (node *root) +{ + if (root) + { + output_tree (root->left); + printf ("%d\n", root->content_left); + output_tree (root->middle); + if (root->content_right >= 0) + printf ("%d\n", root->content_right); + output_tree (root->right); + } +} + +int main (void) +{ + node *root = NULL; + insert_into_tree (&root, 7); + insert_into_tree (&root, 137); + insert_into_tree (&root, 3); + insert_into_tree (&root, 5); + insert_into_tree (&root, 6); + insert_into_tree (&root, 42); + insert_into_tree (&root, 1); + insert_into_tree (&root, 2); + insert_into_tree (&root, 12); + output_tree (root); + return 0; +} diff --git a/20210211/logo-hochschule-bochum-cvh-text-v2.pdf b/20210211/logo-hochschule-bochum-cvh-text-v2.pdf new file mode 120000 index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8 --- /dev/null +++ b/20210211/logo-hochschule-bochum-cvh-text-v2.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum-cvh-text-v2.pdf \ No newline at end of file diff --git a/20210211/logo-hochschule-bochum.pdf b/20210211/logo-hochschule-bochum.pdf new file mode 120000 index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1 --- /dev/null +++ b/20210211/logo-hochschule-bochum.pdf @@ -0,0 +1 @@ +../common/logo-hochschule-bochum.pdf \ No newline at end of file diff --git a/20210211/pgscript.sty b/20210211/pgscript.sty new file mode 120000 index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b --- /dev/null +++ b/20210211/pgscript.sty @@ -0,0 +1 @@ +../common/pgscript.sty \ No newline at end of file diff --git a/20210211/pgslides.sty b/20210211/pgslides.sty new file mode 120000 index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64 --- /dev/null +++ b/20210211/pgslides.sty @@ -0,0 +1 @@ +../common/pgslides.sty \ No newline at end of file diff --git a/20210211/stack-0.c b/20210211/stack-0.c new file mode 100644 index 0000000000000000000000000000000000000000..289aab7602e1e1f9f1e6433b858f295792499b1b --- /dev/null +++ b/20210211/stack-0.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +void push (int x) +{ +} + +int pop (void) +{ + return 42; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-1.c b/20210211/stack-1.c new file mode 100644 index 0000000000000000000000000000000000000000..d1de6e09d718b69a9d255b6c83f6f7815584b430 --- /dev/null +++ b/20210211/stack-1.c @@ -0,0 +1,28 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer] = x; + stack_pointer++; +} + +int pop (void) +{ + return 42; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-2.c b/20210211/stack-2.c new file mode 100644 index 0000000000000000000000000000000000000000..20bed3660cffea7e0a9803451f69ef56a4a04b93 --- /dev/null +++ b/20210211/stack-2.c @@ -0,0 +1,27 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return 42; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-3.c b/20210211/stack-3.c new file mode 100644 index 0000000000000000000000000000000000000000..b20a444d628a88101416097c79b34e0669b24d21 --- /dev/null +++ b/20210211/stack-3.c @@ -0,0 +1,28 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + stack_pointer--; + return stack[stack_pointer]; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-4.c b/20210211/stack-4.c new file mode 100644 index 0000000000000000000000000000000000000000..0d738f95ff81ce1701b4aa8a12df30094b723851 --- /dev/null +++ b/20210211/stack-4.c @@ -0,0 +1,27 @@ +#include <stdio.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + stack[stack_pointer++] = x; +} + +int pop (void) +{ + return stack[--stack_pointer]; +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-5.c b/20210211/stack-5.c new file mode 100644 index 0000000000000000000000000000000000000000..38a187208208488bdb8e988d93442d57730e421e --- /dev/null +++ b/20210211/stack-5.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include <stdlib.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + if (stack_pointer < STACK_SIZE) + stack[stack_pointer++] = x; + else + { + fprintf (stderr, "stack overflow\n"); + exit (1); + } +} + +int pop (void) +{ + if (stack_pointer > 0) + return stack[--stack_pointer]; + else + { + fprintf (stderr, "stack underflow\n"); + exit (1); + } +} + +int main (void) +{ + push (3); + push (7); + push (137); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-6.c b/20210211/stack-6.c new file mode 100644 index 0000000000000000000000000000000000000000..be00e160384be5e4af05831547ed74b636c3bdf0 --- /dev/null +++ b/20210211/stack-6.c @@ -0,0 +1,39 @@ +#include <stdio.h> +#include <stdlib.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + if (stack_pointer < STACK_SIZE) + stack[stack_pointer++] = x; + else + { + fprintf (stderr, "stack overflow\n"); + exit (1); + } +} + +int pop (void) +{ + if (stack_pointer > 0) + return stack[--stack_pointer]; + else + { + fprintf (stderr, "stack underflow\n"); + exit (1); + } +} + +int main (void) +{ + for (int i = 0; i < 42; i++) + push (i); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + printf ("%d\n", pop ()); + return 0; +} diff --git a/20210211/stack-7.c b/20210211/stack-7.c new file mode 100644 index 0000000000000000000000000000000000000000..b583bc281f9ae3acd673ec9ea4de75720084fb50 --- /dev/null +++ b/20210211/stack-7.c @@ -0,0 +1,39 @@ +#include <stdio.h> +#include <stdlib.h> + +#define STACK_SIZE 10 + +int stack[STACK_SIZE]; +int stack_pointer = 0; + +void push (int x) +{ + if (stack_pointer < STACK_SIZE) + stack[stack_pointer++] = x; + else + { + fprintf (stderr, "stack overflow\n"); + exit (1); + } +} + +int pop (void) +{ + if (stack_pointer > 0) + return stack[--stack_pointer]; + else + { + fprintf (stderr, "stack underflow\n"); + exit (1); + } +} + +int main (void) +{ + push (3); + push (7); + push (137); + for (int i = 0; i < 42; i++) + printf ("%d\n", pop ()); + return 0; +}