| @@ -45,7 +45,7 @@ Aus Definitionen: | |||||
| betrachten die Folge der $n$-ten Partialsumme $(s_n)_{n \in \N}$ | betrachten die Folge der $n$-ten Partialsumme $(s_n)_{n \in \N}$ | ||||
| definiert durch: | 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), | .\] Die Reihe $\sum_{k=1}^{\infty} a_k $ konvergiert (divergiert), | ||||
| wenn die Folge der Partialsummen $(s_n)_{n\in\N}$ 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} = 1 + q + q^2 + q^{3} + \ldots | ||||
| .\] $\sum_{k=0}^{\infty} q^{k}$ konvergiert genau | .\] $\sum_{k=0}^{\infty} q^{k}$ konvergiert genau | ||||
| für alle $ q \in \mathbb{C}$ mit $|q| < 1$ und | 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} | \label{geometrischereihe} | ||||
| \end{bsp} | \end{bsp} | ||||
| \begin{proof} | \begin{proof} | ||||
| Folge der Partialsummen | 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 \\ | \frac{1 - q^{n+1}}{1 - q} \quad q \neq 1 & q \neq 1 \\ | ||||
| n + 1 & q = 1 | n + 1 & q = 1 | ||||
| \end{cases} | \end{cases} | ||||
| @@ -48,7 +48,7 @@ | |||||
| .\] $\implies \sum_{n=1}^{\infty} (\frac{1}{2})^{n}$ konvergente | .\] $\implies \sum_{n=1}^{\infty} (\frac{1}{2})^{n}$ konvergente | ||||
| Majorante für $\sum_{n=1}^{\infty} \frac{n}{4^{n}}$. | Majorante für $\sum_{n=1}^{\infty} \frac{n}{4^{n}}$. | ||||
| \item $\sum_{n=1}^{\infty} \frac{1}{\sqrt{n} } $ ist divergent, weil | \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 | $\implies \sum_{n=1}^{\infty} \frac{1}{n}$ divergente | ||||
| Minorante. | Minorante. | ||||
| \end{enumerate} | \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: | \item $\forall n \ge N_0$ gilt: | ||||
| \[ | \[ | ||||
| |a_n| \le q |a_{n-1}| \le \ldots \le q^{n-N_0} |a_{N_0}| | |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. | 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$ | (a_n)_{n\in\N}$ keine Nullfolge $\implies \sum_{n=1}^{\infty} a_n$ | ||||
| divergiert. | divergiert. | ||||
| \end{enumerate} | \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 | Sei $(a_n)_{n\in\N}$, $a_n \in \R_{+}$, eine reelle, positive | ||||
| monoton fallende Nullfolge. Dann gilt | 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} | \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,9 @@ | |||||
| \begin{document} | \begin{document} | ||||
| \begin{aufgabe} | |||||
| \punkte | |||||
| \begin{aufgabe} LIFO vs. FIFO | |||||
| \begin{enumerate} | \begin{enumerate} | ||||
| \item Kunden in einer Bäckerei | \item Kunden in einer Bäckerei | ||||
| @@ -18,6 +20,9 @@ | |||||
| FIFO: Die ältesten Lebensmittel müssen als erstes verbraucht werden. | FIFO: Die ältesten Lebensmittel müssen als erstes verbraucht werden. | ||||
| \item Autos auf einer Autofähre | \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 | FIFO: Das erste Auto steht ganz vorne auf der Fähre und verlässt diese als erstes | ||||
| auf der anderen Seite. | auf der anderen Seite. | ||||
| \item Druckanträge auf einen Drucker | \item Druckanträge auf einen Drucker | ||||
| @@ -34,6 +39,33 @@ | |||||
| \end{aufgabe} | \end{aufgabe} | ||||
| \begin{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} | \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); | |||||
| } | |||||