| @@ -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} | |||
| @@ -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} | |||
| @@ -0,0 +1,147 @@ | |||
| #include<stdio.h> | |||
| // 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)); | |||
| } | |||
| @@ -5,7 +5,7 @@ | |||
| \begin{document} | |||
| \begin{aufgabe} | |||
| \begin{aufgabe} LIFO vs. FIFO | |||
| \begin{enumerate} | |||
| \item Kunden in einer Bäckerei | |||
| @@ -18,6 +18,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 +37,33 @@ | |||
| \end{aufgabe} | |||
| \begin{aufgabe} | |||
| Hase und Igel | |||
| \begin{enumerate}[a)] | |||
| \item Wenn kein Zyklus vorliegt, wird einer \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} | |||
| @@ -0,0 +1,84 @@ | |||
| #include<stdio.h> | |||
| #include<cstdlib> | |||
| // 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); | |||
| } | |||
| @@ -0,0 +1,83 @@ | |||
| #include<stdio.h> | |||
| #include<cstdlib> | |||
| // 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); | |||
| } | |||