PDF

Werbung
R
S
IS
UN
http://www.mpi-sb.mpg.de/~sschmitt/info5-ss01
E R SIT
S
SS 2001
SA
Schmitt, Schömer
IV
A
Grundlagen zu
Datenstrukturen und Algorithmen
A VIE N
Lösungsvorschläge für das 5. Übungsblatt
Letzte Änderung am 16. Mai 2001
Aufgabe 1
a) Berechnen Sie die mittlere Anzahl von Würfen bis zum Auftreten einer Sechs.
Oder allgemeiner:
Ist p die Wahrscheinlichkeit mit der ein bestimmtes Ereignis auftritt und
X = Anzahl der Experimente bis dieses Ereignis auftritt.
Dann ist P (X = i) = p · (1 − p)i−1 .
E(X) =
∞
X
i · p · (1 − p)i−1
i=1
X
p
=
· lim
i · (1 − p)i
n−>∞
1−p
i=1
n
(1 − p)n · ((1 − p) · n + n + (1 − p)) + (1 − p)
p
· lim
1 − p n−>∞
p2
p
0 + (1 − p)
=
·
1−p
p2
1
=
p
=
Da in diesem Fall p = 16 ⇒ E(X) = 6.
b) Berechnen Sie die mittlere Anzahl von Würfen bis jede Augenzahl einmal aufgetreten ist.
Nun ist X = Anzahl der Würfe bis alle Augenzahlen einmal aufgetreten sind bzw
X=
6
X
Yi
i=1
mit Yi
= Anzahl der Würfe vom Auftreten der (i-1)’ten Zahl
bis zum Auftreten der i’ten Zahl
Es gilt: P (Yi = k) = pi (1 − pi )k−1 mit pi =
7−i
6
E(X) = E(
=
⇒ E(Yi ) =
6
X
i=1
6
X
Yi )
E(Yi )
i=1
6
7−i
=
6
X
i=1
6
7−i
6 3
+ +2+3+6
5 2
= 14, 7
= 1+
Aufgabe 2
Definition:
Eine Instanz S des parametrisierten Datentyps b_stack<T> ist eine Sequenz beschränkter Länge
von Elementen des Typs T . Sowohl das Einfügen als auch das Entfernen von Elementen findet
stets an einem Ende der Sequenz statt (Last In - First Out). Die maximale Größe wird bei der
Erzeugung festgelegt.
Erzeugung:
b_stack<T> S(int n)
Erzeugt eine Instanz S des Typs b_stack<T> der Größe n, die Anfangs die leere Sequenz ist.
Operationen:
bool S.isEmpty()
liefert den Wert true zurück, wenn S die leere Sequenz ist, ansonsten false.
void S.push(T x)
hängt das Element x vom Typ T an das Ende von S an, falls |S| < n ist.
T S.pop()
liefert das Element x vom Ende der Sequenz S zurück und entfernt es vom Ende, falls S nicht
die leere Sequenz ist.
Laufzeit:
Wie man leicht sehen kann, geschehen alle Stack-Operationen auf einem Array und finden deshalb
in konstanter Laufzeit statt. is_empty() hat trivialerweise ebenfalls konstante Laufzeit.
Implemetierung:
template<class T>
class b_stack
{
int top;
int size;
array<T> *A;
// zeigt, wieviele Elemente auf dem Stapel liegen
// die totale Groesse des Stapels
// Zeiger auf ein Array aus Typen T
public:
b_stack(int n)
// Konstruktor; n gibt die Groesse an
{
top = 0;
size = n;
A = new array<T>(n); // Zeiger auf ein neues Array der Groesse n biegen
}
~b_stack()
//Destruktor
{
delete A;
}
void push(T x)
{
assert(top<size);
(*A)[top++] = x;
}
T pop()
{
assert(top>0);
return (*A)[--top];
}
bool isEmpty()
{
return top == 0;
}
// ist noch Platz auf den Stapel?
// "oberstes" Element zuweisen, Stapel "erhoehen"
// sind noch Elemente auf dem Stapel?
// oberstes Element zurueckgeben, Stapel "verkleinern"
// Null Elemente? => Stapel leer.
};
Aufgabe 3
Definition:
Eine Instanz S des parametrisierten Datentyps b_queue<T> ist eine Sequenz beschränkter Länge
von Elementen des Typs T . Das Einfügen von Elementen findet stets am Ende, das Entfernen
am Anfang der Sequenz statt (First In - First Out). Die maximale Größe wird bei der Erzeugung
festgelegt.
Erzeugung:
b_queue<T> S(int n)
Erzeugt eine Instanz S des Typs b_queue<T> der Größe n, die Anfangs die leere Sequenz ist.
Operationen:
bool S.isEmpty()
liefert den Wert true zurück, wenn S die leere Sequenz ist, ansonsten false.
void S.enqueue(T x)
hängt das Element x vom Typ T an das Ende von S an, falls |S| < n ist.
T S.dequeue()
liefert das Element x vom Anfang der Sequenz S zurück und entfernt es von dort, falls S nicht
die leere Sequenz ist.
Laufzeit:
Um die Laufzeit von n aufeinanderfolgenden Operationen in Θ(n) zu halten, was bedeutet, daß die
Operationslaufzeiten im Mittel konstant sind, benutzen wir zwei getrennte b_stacks, die ebenso
groß sind wie die Schlange. Einen benutzen wir stets für die Einfügeoperationen, d.h. was auch
immer an die Schlange angefügt werden soll, legen wir oben auf den, sagen wir “linken” Stack.
Erfolgt nun eine dequeue-Operation, so nehmen wir immer das oberste Element vom “rechten”
Stack. Sollte dieser leer sein (z.B. vor der ersten enqueue-Operation) “kippen” wir einfach alle
Elemente von links nach rechts - tatsächlich “kippen”, da die Elemente des enqueue-Stacks danach
in umgekehrter Reihenfolge auf dem dequeue-Stack liegen.
Wir brauchen also bei der ersten dequeue-Operation die Laufzeit Θ(k), wenn davor k enqueueOperationen direkt aufeinander gefolgt sind. Für alle k − 1 nachfolgenden dequeue-Operationen
brauchen wir aber wieder jeweils nur konstante Zeit, egal ob zwischendurch wieder enqueue-t
wird.
Bei n aufeinanderfolgenden, beliebig gemischten de- und enqueue-Operationen wird jedes Element
je höchstens einmal AUF den linken Stapel, VOM linken AUF den rechten gelegt, und wieder
VOM Rechten genommen. Also liegt die Gesamtlaufzeit der Operationen in Θ(n), also amortisiert
kostet eine Operation Θ(1) Zeit.
Implemetierung:
template<class T>
class b_queue
{
int top;
int size;
b_stack<T> *enq_stack;
b_stack<T> *deq_stack;
//
//
//
//
wieder die aktuelle "Laenge" der Schlange
absolute Groesse
der Stack fuer die enqueue-Operationen
und der fuer die dequeue-Operationen
public:
b_queue(int n)
{
top = 0;
size = n;
enq_stack =
// die beiden Stacks mit der Groesse n initialisieren
new b_stack<T>(n);
deq_stack =
new b_stack<T>(n);
}
~b_queue()
{
delete enq_stack;
delete deq_stack;
}
void enqueue(T x)
{
assert(top<size);
top++;
enq_stack->push(x);
}
T dequeue()
{
assert(top>0);
top--;
//Destruktor
// ist noch Platz in der Schlange?
// Schlange "verlaengern"
// und bitte auf dem enqueue-Stapel Platz nehmen
// Elemente in der Schlange?
if (deq_stack->isEmpty())
// Ist der deque-Stapel leer,dann
while(!enq_stack->isEmpty())
// kippen wir den enqueue-Stapel
deq_stack->push(enq_stack->pop()); // umgekehrt auf den dequeue-Stapel
return deq_stack->pop(); // "erstes" Element liegt oben auf dequeue Stapel
}
bool isEmpty()
{
return top == 0;
}
// Null Elemente => Schlange leer.
};
Anmerkung: objekt → memberf unction() entspricht (∗objekt).memberf unction()
Aufgabe 4
a) integer encode(int n,int B)
{
int m = n;
int i = 0;
integer d;
// initialisiere Darstellung
while(m != 0)
{
d.put(i,m % B); // schreibe Rest an aktuelle Stelle (mod)
m = m / B;
// berechne noch zu betrachtende Zahl (div)
i++;
// betrachte naechste Potenz
}
return(d);
// gebe Darstellung zurueck
}
Siehe auch Skript, Seiten 9ff.
b) a = 95110 = 25267
b = 41610 = 11337
Alle Rechnungen sind bzgl. Basis 7 zu verstehen.
2526 * 1133
----------2526
2526
11214
11214
----------3235254
Ergebnis: 25267 · 11337 = 32352547 .
c) Eine B-adische Darstellung wie in der Aufgabenstellung angegeben ist mit B = 1 nicht
sinnvoll möglich! Das ist leicht einzusehen, da man in diesem Fall für alle B i den gleichen
Wert bekommt, nämlich ∀ i : B i = 1.
Sicherlich lassen sich Zahlen auch mit einem Element als Reihen darstellen, allerdings ist der
Sinn der B-adischen Darstellung ja eine Vereinfachung des Zählens (der math. Operationen)
und das ist bei dieser Darstellung sicherlich nicht der Fall!
Herunterladen