Merge branch 'master' of gitea:christian/uni
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -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));
|
||||
}
|
||||
Binary file not shown.
@@ -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}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user