WS 02 - Informatik

Werbung
Algorithmen und Datenstrukturen 1
Ausarbeitung zum Übungsblatt 1 (WS 02)
Klaffenböck Patrick
a.k.a. Yrucrem
Freitag, 18. Oktober 2002
Version 0.6
Danke an franco für den Hinweis das eine Teilfrage bei Aufgabe 8 nicht
behandelt wurde.
Irish machte mich darauf aufmerksam, dass eine Teilfrage von Aufgabe 6
nicht behandelt wurde.
Slater korrigierte eine Laufzeitabschätzung aus Aufgabe 3.
Der LATEX-Source, sowie die neueste Version dieses Dokuments sind unter
yrucrem.dr.ag/studium/algodat 1/uebung.html erhältlich.
Zusammenfassung
Ich veröffentliche meine Lösungen hauptsächlich, damit die Studenten eine Vergleichsmöglichkeit haben, bzw. um denjenigen - die
sich mit einem Beispiel schwer tun - einen Denksanstoß zu geben. Ich
versuche meine Ansätze möglichst genau zu erklären, weil ich denke,
dass man dann besser darüber reden kann. Denn die Lösungen sollen
eine Diskussionsbasis sein, bzw. eine Lernhilfe für diejenigen, denen
der Stoff einfach nicht liegt.
Deshalb freue ich mich auch, über Kritik, Hinweise auf Fehler und
Fragen zu den Lösungen – kurz: wenn sich jemand mit dem Thema
auseinandersetzt.
Was mich weniger freut, ist wenn die Lösungen einfach abgeschrieben und die Erklärungen dazu benutzt werden, sich selbst keine Gedanken über die Fragen machen zu muessen. Aber erstens erkennen es
die Tutoren trotzdem, wenn jemand nur abgeschrieben hat ohne das
Thema zu verstehen und zweitens faellt einem das spätestens bei der
Prüfung auf den Kopf.
Aufgabe 1
Beweisen oder widerlegen Sie, dass f (n) = Θ(n4 ):
(
f (n) =
0.5n4 falls n durch 3 teilbar
n4 − n log n falls n nicht durch 3 teilbar
Da es unendlich viele Zahlen gibt die durch drei Teilbar sind und auch unednlich viele Zahlen nicht durch drei teilbar sind muss für beide Formeln
bewiesen werden, dass sie in Θ(n4 ) sind.
f (n) = 12 n4 :
1
0 ≤ n4 c1 ≤ n4 ≤ n4 c2 | : n4
2
1
0 ≤ c1 ≤ ≤ c2
2
Wenn man zum Beispiel c1 =
Ungleichung ∀n ≥ 1.
1
3
und c2 = 1 wählt, dann gilt die obige
f (n) = n4 − n log n:
0 ≤ n4 c1 ≤ n4 − n log n ≤ n4 c2 | : n4
n4 n log n
−
≤ c2
n4
n4
log n
0 ≤ c1 ≤ 1 − 3 ≤ c2
n
0 ≤ c1 ≤
n
Der Ausdruck log
ist konvergent gegen 0. Wenn wir also das n0 groß genug
n3
wählen, lässt sich diese Funktion auch zwischen zwei Konstanten einsperren.
Zum Beispiel mit:
1
2
c2 = 2
c1 =
n0 = 106
1
Aufgabe 2
Beweisen oder widerlegen Sie die Behauptung
f (n) = Θ(g(n)) ⇒ f (n) = O(2g(n))
Die Definitionen von Θ(n) und O(n):
Θ(g(n)) = {f (n)|∃(c1 , c2 , n0 ) > 0 : 0 ≤ c1 g(n) ≤ f (n) ≤ c2 g(n)∀n ≥ n0 }
O(g(n)) = {f (n)|∃(c, n0 ) > 0 : 0 ≤ f (n) ≤ cg(n)∀n ≥ n0 }
Man sieht also schon aus der Definition, dass f (n) = Θ(g(n)) ⇒ f (n) =
O(g(n)) gilt, denn wenn man den linken Teil der Definition von Θ(n) weglässt
und in der Ungleichung von O(n) das c durch c2 ersetzt, erhält man die gleiche
Ungleichung.
Wenn man beide Seiten der Ungleichung durch g(n) dividiert (eigentlich
reicht es, wenn man durch die höchste Potenz von n in g(n) dividiert), sieht
(n)
kleiner gleich einem Konstanten c sein muss für
man, dass der Ausdruck fg(n)
alle n ≥ n0 .
Wenn man also die Behauptung auf diese Form bringt,
f (n)
f (n)
≤c⇒
≤ 2c
g(n)
g(n)
sieht man schon, dass die Behauptung stimmt – eine Konstante mal zwei ist
ja wieder eine Konstante und nur das ist wichtig.
Aufgabe 3
(a) Θ(n): die Schleife wird ca.
1
3
mal durchlaufen.
(b) Θ(n): die innere Schleife wird beim ersten Mal n + 26 mal ausgeführt,
dann n2 + 26 mal, + n4 + . . . das gibt insgesammt etwa 2n ist also in Θ(n).
2
Aufgabe 4
Wenn man die Definitionen der Notationen O, Ω und Θ (siehe oben) ins
“Deutsche” ürbersetzt, erhäelt man sinngemäßfolgendes:
(n)
Fuer Θ: f (n) = Θ(g(n)) ⇔ man kann fg(n)
zwischen zwei Konstanten c1 und
c2 einschließen. Das muss nicht einmal für alle n gelten, sondern nur für alle
n ≥ n0 . Wobei c1 , c2 und n0 Konstanten sind die nur größer als 0 sein müssen.
Wenn man diese drei Konstanten finden kann, dann ist f (n) = Θ(g(n)).
Analog sieht es bei O und Ω aus, nur dass man eben bei O die kleinere und
bei Ω die größere Konstante nicht braucht. Daraus folgt auch, dass wenn eine
Funkion in Θ(g(n)) ist, dann ist sie auch in O(g(n)) und in Ω(g(n)).
√
Beweis fuer n3 + n = Θ(n3 ):
√
n <= c2 n3 | : n3
√
n3
n
0 <= c1 <= 3 + 3 <= c2
n
n
0 <= c1 n3 <= n3 +
Diese Ungleichung gilt zum Beispiel fuer:
c1 = 1, c2 = 2, n0 = 1
Analog kann man dann zeigen, dass n3 +
√
n 6= O(n2 ).
Gegeben sei nun die Funkion f wie folgt definiert:
(
f (n) =
0.5n2 falls n < 1000
√
n3 + nfalls n ≥ 1000
Welche der folgenden Aussagen sind richtig und welche sind falsch?
Da wir ja nur Aussagen für jene n machen müssen die größer gleich n0 sind
und wenn wir n0 = 1000 setzten, müssen wir nur die Formel betrachten für
n ≥ 1000.
√
f = Ω(n3 ): stimmt, denn n3 +√ n = Ω(n3 )
f = O(n3 ): simmt, denn n3 + n = O(n3 )
3
f = Θ(n3 ): stimmt auf jeden Fall wenn
√ schon die ersten beiden stimmen
f = O(n2 ): stimmt nicht, denn n3 − n wächst sicher schneller als als n2 .
Aufgabe 5
Selection-Sort anhand dieser Folge veranschaulichen: 3, 1, 7, 6, 2, 4, 9, 5,
8.
Durchgang
Feld
1
3 1 7 6 2
2
1 3 7 6 2
3
1 2 7 6 3
4
1 2 3 6 7
5
1 2 3 4 7
6
1 2 3 4 5
7
1 2 3 4 5
8
1 2 3 4 5
1
2
3
4
5
4 9 5 8
4 9 5 8
4 9 5 8
4 9 5 8
6 9 5 8
6 9 7 8
6 9 7 8
6 7 9 8
6
7
8
9
Vergleiche
8
7
6
5
4
3
2
1
Vertauschungen
1
1
1
1
1
0
1
1
36
7
Die fettgeschriebenen Zahlen werden jeweils vertauscht. Bereits am Beginn
des jeweiligen Durchgangs sind die unterstrichenen Zahlen schon an ihren
endgültigen Positionen.
Selection-Sort ist nicht stabil, weil gleich große Elemente aneinander vorbeigetauscht werden können. Zum Beispiel 3a , 5, 3b , 2. 2 ist das kleinste Element
also wird es mit 3a vertauscht → 2, 5, 3b , 3a .
Aufgabe 6
Welches Sortierverfahren ist bei bereits aufsteigend sortierten Daten effizienter, Insertion-Sort oder Merge-Sort?
Insertion-Sort ist in diesem Fall linear (Θ(n)) und Merge-Sort ist in Θ(n log n),
also ist Insertion-Sort effizienter.
4
Betrachten wir die Zahlen folge 1, 2, 3, . . . , n. Insertion-Sort vergleicht 2 mit
1, merkt dass 1 bereits kleiner ist und beginnt sofort den nächsten Schleifendurchlauf. Und das passiert bei allen n Zahlen, es gibt also n Vergleiche
(keine Vertauschungen) → Θ(n).
Merge-Sort teilt, auf jeden Fall das Array so lange in zwei Hälften bis es nur
noch Teilarrays der länge 1 gibt → Θ(n log n).
Die zweite Frage ist, welches der beiden Sortierverfahren im Average-Case
effizienter ist. Im Average-Case liegt Insertion-Sort in Θ(n2 ) und Merge-Sort
liegt immer in Θ(n log n), also ist Merge-Sort im Durchschnittsfall besser.
Aufgabe 7
Der Algorithmus ist abhängig vom Inhalt der Eingabefolge, weil keine unnötigen Datenbewegungen vorkommen (ie. es werden keine Elemente auf sich
selbst verschoben). Im Best-Case haben wir 0 Datenbewegungen und im
Worst-Case Θ(n2 ) Bewegungen.
Die Schlüsselvergleiche sind nicht vom Inhalt der Folge abhängig, sondern
nur von der Anzahl der Elemente.
Hier die Laufzeitfunktion:
T (n) = nc1 +
n−1
X
(n − i + 1)c2 +
n−1
X
n2 −n
2
(n − i)c3 +
i=1
i=1
X
(ti ) c4
i=1
Das ergibt:
n2 −n
2
X
n2 + n − 2
n2 − n
c2 +
c3 +
(ti ) c4 = Θ(n2 )
nc1 +
2
2
i=1
Es ist deswegen erlaubt die innere Schleife nur bis n − i laufen zu lassen,
weil nach jedem Durchlauf der äußeren Schleife ein Element an die richtige
Position gestellt wurde und da Bubble-Sort die Elemente immer vor sich
herschiebt, bis es etwas größeres findet sind immer die letzten i Elemente
5
bereits sortiert. Deswegen macht es keinen Sinn mit der inneren Schleife
über den Index n − i zu gehen, weil dort nichts mehr zu tun ist.
Eigentlich dürfte alles bis auf die letzt Summe klar sein und die will ich jetzt
kurz erklären. Nach jedem Durchlauf der Äusseren Schleife befindet sich das
größte Elemente, der unsortierten Teilfolge, ganz an deren Ende (also an der
richtigen Position). Das kommt davon, dass Bubblesort ein Element so lange
“vor sich her schiebt” bis ein noch größeres Element gefunden wird (und dann
schiebt er das vor sich her, ...). Das bedeutet, dass am Ende jedes Durchlaufes der äußeren Schleife (mit dem Schleifenzähler i) die letzten i Elemente
bereits sortiert sind. Das wiederum bedeutet, dass in diesem Bereich sicher
keine Verschiebungen mehr stattfinden. Sobald also die innere Schleife den
Index (n − i) überschritten hat, kommen keine Verschiebungen mehr vor. Ich
versuche, das kurz zu verdeutlichen.
Ist die äußere Schleife in ihrem ersten Durchlauf ist i = 1, das würde bedeuten
sobald die innere Schleife den Index (n − 1) passiert hat, kommen keine
Verschiebungen mehr hinzu, aber (n − 1) ist sowieso das Maximum für die
innere Schleife.
Am Ende des Ersten Durchgangs ist das größte Element ganz am Ende des
Feldes. i = 2, das heißt ab j = n − 2 gibt es für die inenre Schleife eigentlich
nichts mehr zu tun, das letzte Element ist ja schon an der richtigen Stelle.
Wir summieren jetzt also auf wie oft die Bedingung in Zeile 3 erfüllt sein
könnte und lassen aber die Durchgänge der inneren Schleife weg, die sowieso
nichts mehr bringen.
Die Bedingung könnte bei jedem Durchlauf der äußeren Schleife (n − i)-mal
erfüllt sein. Also beim ersten mal (n − 1)-mal, dann (n − 2)-mal, . . ., dann
Pn−1
2
i = n 2−n -mal
(n − (n − 2))-mal, dann (n − (n − 1))-mal. Es könnte also i=1
sein, dass wir eine Vertauschung haben. Ob wir vertauschen müssen, hängt
natürlich vom Element ab, dass an der Stelle i steht. Wir müssen also an
n2 −n
Stellen schauen ob hier eine Vertauschung nötig ist. Das machen wir
2
2 −n
Pn
mit i=12 ti , wobei ti = 1 wenn an dieser Stelle getauscht werden muss und
ti = 0, wenn nicht getauscht werden muss.
6
Aufgabe 8
Die Zahlenfolge 8, 2, 9, 4, 6, 0, 1, 5 mit Quicksort sortieren.
Was macht Quicksort? Es wählt ein “zerteilendes” Element, das sogenannte
Pivotelement und bringt alle Elemente die kleiner sind auf dessen linke Seite
und alle Elemente die größer sind auf dessen rechte Seite.
Dafür benutzt der Algorithmus zwei Zeigervariablen. i durchläuft das Feld
von links nach rechts und bleibt bei jedem Element stehen, dass grösser
oder gleich dem Pivotelement ist. j geht von rechts nach links und stopt bei
jedem kleineren Element. Wenn beide Zeiger stehengeblieben sind (und i auch
wirklich noch links von j ist) werden diese beiden Elemente ausgetauscht.
Wenn i und j aneinander vorbeilaufen, heißt das, dass links von der Position
an dem das i steht nur Elemente sind, die kleiner sind als das Pivotelement
und rechts davon nur Elemente die größer oder gleich groß sind. Also tauschen
wir das Pivotelement mit dem Element an der Stelle i.
Nach jedem Durchgang steht ein Element genau an der Stelle an die es hingehört. Nun ruft sich Quicksort rekursiv auf um alle Elemente links beziehungsweise rechts des endgültig platzierten Elements zu sortieren.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
i
8
1
1
1
1
1
j
2 9
2 i9
2 0
2 0
2 0j
2 0
i
1 2 0
0
2 1
j
i
2 1
1 2
0
1
Feld
4 6 0
4 6 0j
4j i 6 9
4 5 9
i
4
4
2
4
j
i
5
6
9
6
1j
8
8
8
5
5
5
6
8
8
8j
8
8
6
9
i
9
9
9
Eine Zahlenfolge die von Quick-sort im Best-Case sortiert wird, wäre etwa:
7
1, 3, 2, 6, 5, 7, 4. Das Pivotelement halbiert jedes mal die Zahlenfolge. Dadurch tritt am öftesten der Fall ein, dass neben den Pivotelement nur noch
einelementige Felder sind (die ja dann von Quick-Sort übersprungen werden.
Aufgabe 9
Merge-Sort soll absteigend sortieren. Dafür muss man nur im Pseudocode
von Algorithmus 4 (Merge(A, l, m, r), Seite 34 im Skriptum) das “ ≤00 ind
Zeile 5 durch ein “ ≥00 ersetzten.
Aufgabe 10
Warum sortiert der Algorithmus nicht jede Zahlenfolge korrekt?
Wenn das größte Element an der Stelle A[l] steht, gibt es ein Problem. Zuerst
wird nämlich das kleinste Element mit dem an der Stelle A[l] vertauscht,
und dann wird dieses Element (weil der Algorithmus glaubt, dass dort immer
noch das größte Element steht) mit A[r] vertauscht. Zum Beispiel: 5, 4, 1,
2, 3 wird zu 1, 4, 5, 2, 3 und das zu 3, 4, 5, 2, 1. Eigentlich sollte
aber das kleinste ganz links und das größte ganz rechts stehen.
Den Algorithmus so ändern, dass er funktioniert.
Man darf nicht zuerst beide Positionen bestimmen und dann beide vertauschen, sondern man muss zuerst die Position des kleinsten Elementes bestimmen, es an den linken Rand tauschen, dann die Position des größten
Elementes bestimmen und es an den rechten Rand tauschen. Man muss also
nur die 4. Zeile im Pseudcode (max = ...) zwischen die beiden VertauscheZeilen schieben.
8
Herunterladen