Lösungsvorschläge

KIT
Jun.-Prof. Henning Meyerhenke, Jun.-Prof. Dennis Hofheinz
Institut f¨
ur Theoretische Informatik
Christian Staudt, Christoph Striecks
¨
3. Ubungsblatt
zu Algorithmen I im SS 2015
https://crypto.iti.kit.edu/algo-sose15
{staudt,striecks}@kit.edu
Mit L¨
osungsvorschl¨
agen
Aufgabe 1
(Rekursionsgleichungen, 4 + 4 Punkte)
a) Zeigen Sie mittels vollst¨
andiger Induktion, dass f¨
ur
(
2
T (n) =
2T (dn/2e) + n2
falls n = 1,
falls n ≥ 2,
die Ungleichung T (n) ≤ 2n2 gilt. Dabei sei n eine Zweierpotenz.
b) Zeigen Sie mittels Substitution, dass die L¨osung zu
(
9
falls n = 27,
1/3 T (n) =
9T ( n
) + log3 n falls n ≥ 28,
i
in Θ log2 n liegt. Dabei sei n = 33 , f¨
ur i ∈ N.
L¨
osungsvorschlag:
a)
– Induktionsanfang: n = 1, T (1) = 2 ≤ 2
– Induktionsbehauptung: T (n) ≤ 2n2
– Induktionsschritt: n > 1, n nach 2n, T (2n) = 2T (n) + (2n)2 ≤ 4n2 + 4n2 = 8n2 = 2(2n)2
b) Wir setzen m = log3 n und erhalten T (33 ) = 9 und T (3m ) ≤ 9T (3m/3 ) + m, f¨
ur 3m ≥ 28. Wir
setzen S(m) = T (3m ) und erhalten
(
9
falls m = 3,
S(m) =
9S(m/3) + m falls m ≥ 4.
Das Mastertheorem aus der
Vorlesung liefert S(m) = Θ mlog3 9 = Θ m2 . Somit gilt S(m) =
T (3m ) = T (n) = Θ log2 n .
Aufgabe 2
(Einfach verkettete Listen, 8 Punkte)
Gegeben sei folgende Implementierung der Datenstruktur einfach verkettete Liste: Eine Liste besteht
aus Knoten (Objekte vom Typ Node), die jeweils ein Listenelement (data) und eine Referenz (next)
auf den n¨achsten Knoten der Liste enthalten. Eine Liste wird als Referenz auf ihren ersten Knoten
u
¨ bergeben. Der letzte Knoten der Liste enth¨alt eine leere Referenz (null). Seien L1 und L2 zwei
einfach verkettete Listen, die Zahlen in aufsteigend sortierter Reihenfolge enthalten. Beide Listen
sollen so miteinander verflochten werden, dass die resultierende einfach verkettete Liste M alle Knoten
von L1 und L2 enth¨
alt und die Elemente in aufsteigender Reihenfolge sortiert sind. Schreiben Sie in
Pseudocode eine Funktion, die L1 und L2 als Eingabe nimmt und M ausgibt. Ihre Funktion darf nur
O(1) zus¨atzlichen Speicher benutzen und soll die Knoten der Eingabelisten wiederverwenden. An einem
Knoten kann nur das Feld next ver¨
andert werden.
1
Lo
¨sungsvorschlag:
Es folgt eine m¨
ogliche Implementierung der Datenstruktur und des Algorithmus in Python. (Die
Angabe des Algorithmus in Pseudocode oder als klar verst¨andliche Implementierung in einer anderen
realen Programmiersprache ist nat¨
urlich ebenfalls eine g¨
ultige L¨osung.)
class Node:
""" Simple singly-linked list node"""
def __init__(self, data, next):
""" Construct a list node from a data element and a reference to the following
node"""
self.data = data
self.next = next
class SortedListMerger:
""" Sorted linked-list merging algorithm"""
def __init__(self, h1, h2):
"""Construct with two heads of sorted lists as input"""
self.h1 = h1
self.h2 = h2
self.head = None
# head of result list
self.tail = None
# tail of result list
def next(self):
""" Returns next node in order, separated from origin list"""
ret = None
# border cases in which at least one input list is already empty
if (self.h1 is None) and (self.h2 is None):
return None
if (self.h1 is None) and (self.h2 is not None):
ret = self.h2
self.h2 = self.h2.next
# advance h2
return ret
if (self.h2 is None) and (self.h1 is not None):
ret = self.h1
self.h1 = self.h1.next
# advance h1
return ret
# regular case
if self.h1.data < self.h2.data:
ret = self.h1
self.h1 = self.h1.next
# advance h1
else:
ret = self.h2
self.h2 = self.h2.next
# advance h2
ret.next = None
# cut node from input list
return ret
def merge(self):
""" Merge lists given in constructor and return head of result list"""
next = self.next()
self.head = next
self.tail = next
while next is not None:
next = self.next()
self.tail.next = next
self.tail = next
return self.head
Beispielaufruf
h1 = Node(1, Node(4, Node(8, None)))
h2 = Node(2, Node(4, Node(5, Node(17, Node(42, None)))))
merger = SortedListMerger(h1, h2)
h3 = merger.merge()
print(h3)
Aufgabe 3
(Amortisierte Analyse, 5 + 2 Punkte)
Gegeben sei eine Datenstruktur, auf der eine Sequenz hσ1 , . . . , σn i von Operationen ausgef¨
uhrt wird.
Die Operation σi , f¨
ur 1 ≤ i ≤ n, ben¨
otigt i3 Anweisungen, wenn i eine Dreierpotenz ist; anderenfalls
ben¨otigt eine Operation 1 Anweisung.
2
a) Geben Sie eine geschlossene Form T (n) f¨
ur die Kosten von n Operationen an. Dabei sei n = 3m ,
f¨
ur m ∈ N.
b) Geben Sie die amortisierten Kosten pro Operation an.
L¨
osungsvorschlag:
a) Wir zeigen T (n) ∈ O n3 . Sei cost(i) die Kosten-Funktion f¨
ur die i-te Operation. Wir setzen
P3m
m
zun¨achst S(m) := T (3 ) = T (n) = i=1 cost(i) mit S(0) := 1. Weiterhin ist n = 3m . Nun
stellt man S(m) als Rekurrenz dar, um nachher eine Summenformel zu bekommen. Das u
¨berlegt
man sich folgendermaßen: Beim Inkrementieren von m − 1 auf m, f¨
ur m wie oben, haben alle
Operationen zwischen 3m−1 und 3m die Kosten 1. Das sind genau 3m − 3m−1 − 1 viele. Die letzte
Operation hat Kosten cost(3m ) = (3m )3 . Also ist
S(m) = S(m − 1) + (3m )3 + (3m − 3m−1 − 1) = S(m − 1) + 33m + 2 · 3m−1 − 1.
Ausrollen der Rekurrenz ergibt:
S(m) =
m
X
(27i + 2 · 3i−1 − 1) + S(0).
i=1
Diese Summenformel vereinfacht man zu:
S(m) =
1 − 27m+1
1 − 3m
27 3m
27
−1+2·
−m+1=
· 3 + 3m − m − .
−26
−2
26
26
Und da m = log3 n gilt, erh¨
alt man durch R¨
uck-Substituieren eine Formel f¨
ur T (n):
T (n) =
27
27 3
· n + n − log3 n −
26
26
(falls n eine Dreierpotenz ist).
b) Als amortisierte Kosten pro Operation ergibt sich
T (n)
27 2
log3 n
27
=
·n +1−
−
.
n
26
n
26n
Damit gilt T (n)/n ∈ O n2 , f¨
ur T (n) aus a).
3