diff --git a/ws2019/ana/lectures/analysis.pdf b/ws2019/ana/lectures/analysis.pdf index 3f0fba0..63f7a3a 100644 Binary files a/ws2019/ana/lectures/analysis.pdf and b/ws2019/ana/lectures/analysis.pdf differ diff --git a/ws2019/ana/lectures/analysis13.pdf b/ws2019/ana/lectures/analysis13.pdf index db285a1..022893a 100644 Binary files a/ws2019/ana/lectures/analysis13.pdf and b/ws2019/ana/lectures/analysis13.pdf differ diff --git a/ws2019/ana/lectures/analysis13.tex b/ws2019/ana/lectures/analysis13.tex index 3cd406e..5c1058b 100644 --- a/ws2019/ana/lectures/analysis13.tex +++ b/ws2019/ana/lectures/analysis13.tex @@ -45,7 +45,7 @@ Aus Definitionen: betrachten die Folge der $n$-ten Partialsumme $(s_n)_{n \in \N}$ definiert durch: \[ - s_n := \sum_{k=1}^{\infty} a_k + s_n := \sum_{k=1}^{n} a_k .\] Die Reihe $\sum_{k=1}^{\infty} a_k $ konvergiert (divergiert), wenn die Folge der Partialsummen $(s_n)_{n\in\N}$ konvergiert (divergiert). @@ -65,14 +65,14 @@ Aus Definitionen: \sum_{k=0}^{\infty} q^{k} = 1 + q + q^2 + q^{3} + \ldots .\] $\sum_{k=0}^{\infty} q^{k}$ konvergiert genau für alle $ q \in \mathbb{C}$ mit $|q| < 1$ und - es gilt $\sum_{0=1}^{\infty} q^{k} = \frac{1}{1-q}$. + es gilt $\sum_{k=0}^{\infty} q^{k} = \frac{1}{1-q}$. \label{geometrischereihe} \end{bsp} \begin{proof} Folge der Partialsummen \[ - s_n = \sum_{k=0}^{\infty} q^{k} = \begin{cases} + s_n = \sum_{k=0}^{n} q^{k} = \begin{cases} \frac{1 - q^{n+1}}{1 - q} \quad q \neq 1 & q \neq 1 \\ n + 1 & q = 1 \end{cases} diff --git a/ws2019/ana/lectures/analysis14.tex b/ws2019/ana/lectures/analysis14.tex index 6e51eeb..21c1b99 100644 --- a/ws2019/ana/lectures/analysis14.tex +++ b/ws2019/ana/lectures/analysis14.tex @@ -48,7 +48,7 @@ .\] $\implies \sum_{n=1}^{\infty} (\frac{1}{2})^{n}$ konvergente Majorante für $\sum_{n=1}^{\infty} \frac{n}{4^{n}}$. \item $\sum_{n=1}^{\infty} \frac{1}{\sqrt{n} } $ ist divergent, weil - $\frac{1}{\sqrt{n} } \ge \frac{1}{n}$ ($\sqrt{n} \ge 1$ + $\frac{1}{\sqrt{n} } \ge \frac{1}{n}$ ($\sqrt{n} \ge 1$) $\implies \sum_{n=1}^{\infty} \frac{1}{n}$ divergente Minorante. \end{enumerate} @@ -74,9 +74,9 @@ Kostina glaubt, dass das so stimmt, aber offensichtlich ist sie sich nicht siche \item $\forall n \ge N_0$ gilt: \[ |a_n| \le q |a_{n-1}| \le \ldots \le q^{n-N_0} |a_{N_0}| - .\] $\implies \frac{|a_{N_0}}{q^{N_0}} \sum_{n=1}^{\infty} q^{n}$ + .\] $\implies \frac{|a_{N_0}|}{q^{N_0}} \sum_{n=1}^{\infty} q^{n}$ ist konvergente Majorante. - \item $|a_n| \ge |a_{n-1}| \ge \ldots \ge |a_n| \implies + \item $|a_n| \ge |a_{n-1}| \ge \ldots \ge |a_{N}| \implies (a_n)_{n\in\N}$ keine Nullfolge $\implies \sum_{n=1}^{\infty} a_n$ divergiert. \end{enumerate} @@ -131,7 +131,7 @@ Kostina glaubt, dass das so stimmt, aber offensichtlich ist sie sich nicht siche Sei $(a_n)_{n\in\N}$, $a_n \in \R_{+}$, eine reelle, positive monoton fallende Nullfolge. Dann gilt \[ - \sum_{k=1}^{\infty} a_k \text{ konvergent } \iff \sum_{k=1}^{\infty} 2^{k} a_{2k} \text{ konvergent} + \sum_{k=1}^{\infty} a_k \text{ konvergent } \iff \sum_{k=1}^{\infty} 2^{k} a_{2^{k}} \text{ konvergent} .\] \end{satz} diff --git a/ws2019/ipi/uebungen/haseigel.cpp b/ws2019/ipi/uebungen/haseigel.cpp new file mode 100644 index 0000000..ffc6d91 --- /dev/null +++ b/ws2019/ipi/uebungen/haseigel.cpp @@ -0,0 +1,147 @@ +#include + +// Ein Listenelement +struct IntListElem { + IntListElem* next; // Zeiger auf nächstes Element + int value; // Daten zu diesem Element +} ; + +// Eine Liste +struct IntList { + int count; // Anzahl Elemente in der Liste + IntListElem* first; // Zeiger auf erstes Element der Liste +} ; + + +// Initialisiere eine Listenstruktur +void empty_list (IntList* l) +{ + l->first = 0; // 0 ist keine gueltige Adresse: Liste ist leer + l->count = 0; +} + +// Fuege ein Element nach einem gegebenem ein +void insert_in_list (IntList* list, IntListElem* where, IntListElem* ins) +{ + if (where==0) // fuege am Anfang ein + { + ins->next = list->first; + list->first = ins; + list->count = list->count + 1; + } + else // fuege nach where ein + { + ins->next = where->next; + where->next = ins; + list->count = list->count + 1; + } +} + +// Entferne ein Element nach einem gegebenem +// Liefere das entfernte Element zurueck +IntListElem* remove_from_list (IntList* list, IntListElem* where) +{ + IntListElem* p; // das entfernte Element + + // where==0 dann entferne erstes Element + if (where==0) + { + p = list->first; + if (p!=0) + { + list->first = p->next; + list->count = list->count - 1; + } + return p; + } + + // entferne Element nach where + p = where->next; + if (p!=0) + { + where->next = p->next; + list->count = list->count - 1; + } + return p; +} + +// creates a cyclic list with a linear part of k elements +// and a cyclic part of n elements +IntList* make_cyclic_list(int k, int n) { + IntList* list = new IntList(); + empty_list(list); + + // create cyclic list of length n + if (n > 0) { + // create last element of list (its inserted first) + IntListElem* last = new IntListElem(); + last->value = n+k; + // insert the (now first, but later) last element into the list + insert_in_list(list, 0, last); + // now iterate over every other number + for (int i = n+k-1; i > k; i--) { + // and create a new list element + IntListElem* elem = new IntListElem(); + // with the given number + elem->value = i; + // and add it to the list in the very beginning + insert_in_list(list, 0, elem); + } + // make the last element reference the first one + last->next = list->first; + } + IntListElem* firstCyclic = list->first; + // add a linear part + for (int i = k; i > 0; i--) { + // create new list element + IntListElem* elem = new IntListElem(); + // with given value + elem->value = i; + // and insert in the very beginning + insert_in_list(list, 0, elem); + // if it is the (first inserted, but later) last element of the linear + // part, make it point to the first cyclic element + if (i == k) { + elem->next = firstCyclic; + } + } + return list; +} + +// Hase-Igel Algorithmus zum Finden eines Zyklus in einer Liste +int hase_igel(IntList* list) { + // create igel, that goes on by one + IntListElem* igel = list->first; + // create hase that always skips one element + IntListElem* hase = list->first; + // count the number of steps needed + int n = 0; + // this is the first occurence of a cycle + int first = 0; + // move forward with igel and hase until we hit the end of the list + while (igel != 0 && hase != 0) { + // increment igel and hase + igel = igel->next; + hase = hase->next->next; + // increment the step counter + n++; + // if igel and hase point to the same element, there + // has to be a cycle + if (igel == hase) { + // save the first occurence + if (first == 0) { + first = n; + // if we find the second one, return the difference + } else { + return n - first; + } + } + } + // if there is an end, there can't be a cycle + return 0; +} + +int main() { + IntList* list = make_cyclic_list(10, 0); + printf("Laenge des Zyklus: %d\n", hase_igel(list)); +} diff --git a/ws2019/ipi/uebungen/ipi7.pdf b/ws2019/ipi/uebungen/ipi7.pdf index 83212bf..09a3db8 100644 Binary files a/ws2019/ipi/uebungen/ipi7.pdf and b/ws2019/ipi/uebungen/ipi7.pdf differ diff --git a/ws2019/ipi/uebungen/ipi7.tex b/ws2019/ipi/uebungen/ipi7.tex index 0eaa8e4..6b4f82a 100644 --- a/ws2019/ipi/uebungen/ipi7.tex +++ b/ws2019/ipi/uebungen/ipi7.tex @@ -5,7 +5,9 @@ \begin{document} -\begin{aufgabe} +\punkte + +\begin{aufgabe} LIFO vs. FIFO \begin{enumerate} \item Kunden in einer Bäckerei @@ -18,6 +20,9 @@ FIFO: Die ältesten Lebensmittel müssen als erstes verbraucht werden. \item Autos auf einer Autofähre + Def. (Autofähre). Eine Fähre mit einer Auffahrt und einer Ausfahrt, jedes Auto + befährt die Fähre nur vorwärts. + FIFO: Das erste Auto steht ganz vorne auf der Fähre und verlässt diese als erstes auf der anderen Seite. \item Druckanträge auf einen Drucker @@ -34,6 +39,33 @@ \end{aufgabe} \begin{aufgabe} + Hase und Igel + \begin{enumerate}[a)] + \item Wenn kein Zyklus vorliegt, wird der \textit{Hase} zuerst auf Null zeigen. + Falls der Zeiger des \textit{Hasen} aber den \textit{Igel} überrundet, muss ein + Zyklus vorliegen, Das wird dann erkannt, wenn \textit{Hase} und \textit{Igel} zum + gleichen Zeitpunkt auf das selbe Element zeigen. Der Abstand von \textit{Hase} zu + \textit{Igel} wird dabei immer kleiner, sodass dies in endlicher Zeit erreicht wird. + + Die Länge des Zyklus wird erkannt durch die Differenz der Schrittzahlen, des ersten + Aufeinandertreffens und dem zweiten. + \item siehe \textit{haseigel.cpp} + \end{enumerate} +\end{aufgabe} + +\begin{aufgabe} + Warteschlangen + \begin{enumerate}[a)] + \item siehe \textit{queue\_einfach.cpp} + \item siehe \textit{queue.cpp} + \item Die Version der einfach verketteten Liste braucht ca. 2550 mal so lang, wie die zweite. Dies liegt + an der Komplexität O(n) des Hinzufügens eines Elements für + eine einfach verkettete Liste, da hier durch die ganze Liste iteriert werden muss, um das letzte + Element zu finden. Bei einer doppelt verketteten Liste liegt eine Komplexität + von O(1) vor, da hier direkt auf das letzte Element zugegriffen werden kann. + Das Entfernen am Listenanfang ist immer eine O(1) Operation, weil hier direkt in beiden + Fällen der Pointer auf das erste Element verwendet werden kann. + \end{enumerate} \end{aufgabe} diff --git a/ws2019/ipi/uebungen/queue.cpp b/ws2019/ipi/uebungen/queue.cpp new file mode 100644 index 0000000..d1e76b8 --- /dev/null +++ b/ws2019/ipi/uebungen/queue.cpp @@ -0,0 +1,84 @@ +#include +#include + +// Ein Queue Element +struct QueueElem { + QueueElem* next; // Zeiger auf nächstes Element + QueueElem* previous; // Zeiger auf vorheriges Element + int value; // Daten zu diesem Element +} ; + +// Eine Queue +struct Queue { + int count; // Anzahl Elemente in der queuee + QueueElem* first; // Zeiger auf erstes Element der queue + QueueElem* last; // Zeiger auf letztes Element der queue +} ; + + +// Initialisiere eine queue +void empty_queue (Queue* l) +{ + l->first = 0; // 0 ist keine gueltige Adresse: queue ist leer + l->last = 0; + l->count = 0; +} + +// Fuege neues Element am Ende der Schlange ein +void add_to_queue(Queue* queue, QueueElem* elem) +{ + if (queue->last == 0) { + queue->first = elem; + queue->last = elem; + } else { + queue->last->next = elem; + elem->next = 0; + elem->previous = queue->last; + queue->last = elem; + } + queue->count = queue->count + 1; +} + +// Remove last Element from queue and return it +QueueElem* remove_from_queue (Queue* queue) +{ + if (queue->first == 0) { + return 0; // return null if queue is empty + } + QueueElem* p; + p = queue->first; + queue->first = p->next; + queue->count = queue->count -1; + return p; +} + +// print a queue +void print_queue(Queue* queue) { + // index pointer + QueueElem* current = queue->first; + printf("Queue: "); + // print every element until the last + while (current != 0) { + printf("%d ", current->value); + current = current->next; + } + printf("\n"); +} + +int main() { + // create a queue + Queue* queue = new Queue(); + empty_queue(queue); + // and some elements + for (int i = 0; i < 100000; i++) { + QueueElem* elem = new QueueElem(); + elem -> value = rand(); + add_to_queue(queue, elem); + } + // and remove them again + for (int i = 0; i < 100000; i++) { + remove_from_queue(queue); + } + // check if queue is empty + print_queue(queue); +} diff --git a/ws2019/ipi/uebungen/queue_einfach.cpp b/ws2019/ipi/uebungen/queue_einfach.cpp new file mode 100644 index 0000000..b21770b --- /dev/null +++ b/ws2019/ipi/uebungen/queue_einfach.cpp @@ -0,0 +1,83 @@ +#include +#include + +// Ein Schlangenelement +struct QueueElem { + QueueElem* next; // Zeiger auf nächstes Element + int value; // Daten zu diesem Element +} ; + +// Eine Schlange +struct Queue { + int count; // Anzahl Elemente in der Liste + QueueElem* first; // Zeiger auf erstes Element der Liste +} ; + +// Initialisiere eine Schlange +void empty_queue (Queue* l) +{ + l->first = 0; // 0 ist keine gueltige Adresse: Liste ist leer + l->count = 0; +} + +// Fuege ein Element ans Ende der Schlange an +void add_to_queue (Queue* queue, QueueElem* elem) +{ + // Laufpointer + QueueElem* current = queue->first; + if (queue->first == 0) { // if queue is empty, put the new element as the first one + queue->first = elem; + return; + } + // find last element of list + while (current->next != 0) { + current = current->next; + } + current->next = elem; // set new element as the follower of the old last one + queue->count = queue->count + 1; // increment queue size +} + +// Entferne das erste Element der Schlange +QueueElem* remove_from_queue(Queue* queue) +{ + QueueElem* p; // das entfernte Element + if (queue->first == 0) { // check if list is empty + return p; // then just return null pointer + } else { + p = queue->first; // return the first element of the queue + queue->first = p->next; // set the second to be the new first + queue->count = queue->count-1; // decrement queue size + return p; // return the removed element + } +} + +// print a queue +void print_queue(Queue* queue) { + // index pointer + QueueElem* current = queue->first; + printf("Queue: "); + // print every element until the last + while (current != 0) { + printf("%d ", current->value); + current = current->next; + } + printf("\n"); +} + +int main() { + // create a queue + Queue* queue = new Queue(); + empty_queue(queue); + // and some elements + for (int i = 0; i < 100000; i++) { + QueueElem* elem = new QueueElem(); + elem -> value = rand(); + add_to_queue(queue, elem); + } + // and remove them again + for (int i = 0; i < 100000; i++) { + remove_from_queue(queue); + } + // check if queue is empty + print_queue(queue); +}