Aufgabenstellung: Ein vom Benutzer angegebener arithmetischer

Werbung
Algorithmen und Datenstrukturen
Fachhochschule Regensburg
Komplexitätsanalyse, Laufzeitberechnung,
Big-O-Notation
4. Übungsblatt
Algorithmen und Datenstrukturen
Name: ________________________
Lehrbeauftragter: Prof. Sauer
Vorname: _____________________
Laufzeitberechnung
Die Laufzeit ist bestimmt durch die Anzahl der durchgeführten elementaren Operationen
(Grundrechenarten, Vergleiche, Feldzugriffe, Zugriffe auf die Komponenten einer Struktur, etc.) Die
Angabe der Laufzeit in Abhängigkeit von konkreten Eingabewerten ist im Allg. nicht möglich oder sehr
aufwendig. Daher betrachtet man die Laufzeit häufig in Abhängigkeit von der Größe (dem Umfang)
der Eingabe.
Definition: T(n) = Anzahl der elementaren Operationen, die zur Bearbeitung einer Eingabe der Größe
n bearbeitet werden.
Eine Analyse der Laufzeit bezieht sich auf den besten, den schlechtesten und den mittleren Fall:
-Tmin(n) = minimale Anzahl der Operationen, die durchgeführt werden, um eine Eingabe der Größe n
zu bearbeiten.
- Tmax(n) = maximale Anzahl der elementaren Operationen, die durchgeführt werden, um eine Eingabe
der Größe n zu bearbeiten.
Ist eine Wahrscheinlichkeitsverteilung der Eingabedaten gegeben, kann auch eine mittlere Laufzeit
Tmit(n) ermittelt werden.
Bsp.: Sequentielle Suche in Folgen
Gegeben ist eine Zahl n ≥ 0 , n Zahlen a1, a2, …, an (alle verschieden), eine Zahl b.
Gesucht ist der Index i = 1,2,…,n, so dass b == ai, falls ein Index existiert. Andernfalls ist i =
n+1.
Lösung: i = 1; while (i <= n && b != ai) i = i + 1;
Aufwand der Suche:
Ergebnis hängt von der Eingabe ab, d.h. von n, a1, …, an und b
1. erfolgreiche Suche (wenn b == ai): S = i Schritte
2. erfolglose Suche S = n+1 Schritte
Ziel: globalere Aussagen, die nur von einer einfachen Größe abhängen, z.B. von der Länge n der
Folge.
Fragen: 1) Wie groß ist S für gegebenes n im schlechtesten Fall?
2) Wie groß ist S für gegebenes n im Mittel
Analyse für erfolgreiche Suche:
- im schlechtesten Fall: b wird erst im letzten Schritt gefunden: b = an , S = n im schlechtesten Fall
- im Mittel
- Wiederholte Anwendung mit verschiedenen Eingaben
- Annahme über Häufigkeit: Wie oft wird b an erster, zweiter, … letzter Stelle gefunden?
- Insgesamt für N-Suchvorgänge
N
N
N
N
N n(n + 1)
n +1
⋅ 1 + ⋅ 2 + ... + ⋅ n = (1 + 2 + ... + n ) = ⋅
=N
n
n
n
n
n
2
2
n +1
M
Schritte, also S =
im Mittel bei Gleichverteilung
- für eine Suche S =
N
2
M =
1
Algorithmen und Datenstrukturen
Asymptotische Analyse (O-Notation) 1
(Analyse der Komplexität durch Angabe einer Funktion f : N → N als Maß für den Aufwand)
Definition: f (n) ist in der Größenordnung von g (n ) „ f ( n) = O ( g ( n)) “, falls Konstante c und n0
existieren 2 , so dass f ( n) ≤ c ⋅ g ( n) für n ≥ n0 .
f ( n)
ist für genügend große n durch eine Konstante c beschränkt, d.h. f wächst nicht schneller als g.
g ( n)
Ziel der Charakterisierung T ( n) = O ( g ( n)) ist es, eine möglichst einfache Funktion g (n ) zu finden.
Bspw. ist T ( n ) = O ( n) besser als T ( n) = O (5n + 10) . Wünschenswert ist auch die
Charakterisierung der Laufzeit mit einer möglichst kleinen Größenordnung.
Die O-Natation besteht in der Angabe einer asymptotischen oberen
Aufwandsfunktion (Wachstumsgeschwindigkeit bzw. Größenordnung)
Schranke
für die
Vorgehensweise bei der Analyse
Die Algorithmen werden gemäß ihrer Kontrollstruktur von innen nach außen analysiert. In der Laufzeit,
die sich dann ergibt, werden anschließend die Konstanten durch den Übergang zur O-Notation
beseitigt.
Vorgehensweise für Kontrollstrukturen
Anweisungen: Anweisungen, die aus einer konstanten Anzahl von elementaren Operationen
bestehen, erhalten eine konstante Laufzeit.
Sequenz A1,A2,…,An. Werden für die einzelnen Anweisungen, die Laufzeiten T1, T2,…,Tn ermittelt,
dann ergibt sich für die Sequenz die Laufzeit T=T1+T2+…+Tn
Schleife, die genau n-mal durchlaufen wird, z.B. for-Schleife ohne break: for (i=1;i<=n;i++) A;
Wird für A die Laufzeit Ti ermittelt, dann ergibt sich als Laufzeit für die for-Schleife T =
n
∑T
i =1
i
.
Eigentlich müsste zu Ti noch eine Konstante C1 für i <=n und i++ und C2 für i = 1 hinzugezählt
werden. Beim späteren Übergang zur O-Notation würde die Konstanten jedoch wegfallen 3 .
Fallunterscheidung (mit else-Teil): if (B) A1, else A2; Hier muß zwischen der Laufzeit im
besten und schlechtesten Fall unterschieden werden: Tmin=min(T1,T2), Tmax=max(T1,T2), wobei T1 die
Laufzeit für A1 und T2 die Laufzeit für A2 ist. Man geht davon aus, dass die Bedingung B konstante Zeit
benötigt und wegen des späteren Übergangs zur O-Notation einfachheitshalber nicht mitgezählt
werden muß.
Schleife mit k-maligen Durchläufen, wobei n1<=k<=n2. Diese tritt typischerweise bei while-Schleifen
auf. Es muß dann eine Analyse für den besten Fall (k=n1) und den schlechtesten Fall (k=n2)
durchgeführt werden.
Rekursion mit n → n − 1 : Es ergeben sich rekursive Gleichungen für die Laufzeiten
Bsp.: rekursive Fakultätsberechnung
int fak(int n)
{
if (n == 0) return 1;
else return n*fak(n-1);
}
Man erhält folgende Laufzeit: Tn = C 0
für n = 0
Tn = C1 + T (n − 1) ) für n > 0
Durch wiederholtes Einsetzen: T ( n) = C1 + C1 + ... + C1 + C 0 = O ( n)
1442443
n − mal
Rekursion mit Teile und Herrsche.
1
2
Skriptum, 1.2.6.2
geeignetes n0 und c müssen angegeben werden, um zu zeigen, dass f ( n) = O( g ( n)) gilt
3
vgl. Skriptum, 1.2.7
2
Algorithmen und Datenstrukturen
f ( x, n )
{ if (n == 1)
(1)
{ // Basisfall
/* löse Pr oblem direkt , Ergebnis sei loes * /
return loes;
}
else { // Teileschritt
/* teile x in 2Teilprobleme x1und x 2 jeweils derGröße n / 2 * /
loe1 = f ( x1, n / 2);
loe2 = f ( x 2, n / 2);
// Herrscheschritt
/* Setze Loesung loes für x aus loe1und loe2 zusammen * /
return loes;
( 2)
(3)
}
}
Für den Basisfall (1) wird eine konstante Anzahl C0 Operationen angesetzt. (2) und (3) benötigen
linearen Aufwand und damit C1 ⋅ n Operationen.
T ( n) = C 0
falls n = 1
T (n) = C1 ⋅ n + 2 ⋅ T (n / 2) 4 5
Durch Einsetzen ergibt sich: T (n) = C1 n + 2(C1 ⋅ n / 2 + 2T (n / 4) ) = 2 ⋅ C1 ⋅ n + 4 ⋅ T (n / 4) )
Durch nochmaliges Einsetzen ergibt sich: T (n) = 3 ⋅ C1 ⋅ n + 8 ⋅ T (n / 8) )
T (n) = log 2 (n) ⋅ C1 ⋅ n + 2 log n T (1)
log n
Mit 2
= n und T (1) = C 0 erhält man: T (n) = C1 ⋅ n ⋅ log 2 (n) + C 0 ⋅ n
Zur Lösung von Rekurrenzgleichungen haben sind
2 Verfahrenstechniken bekannt:
Substitutionsmethode bzw. Mastertheorem.
Lösung mit der Substitutionsmethode:
„Rate eine Lösung“ (z.B. über den Rekursionsbaum)
Beweise die Korrektheit der Lösung per Induktion
Lösung mit dem Mastertheorem:
Mit dem Mastertheorem kann man sehr einfach Rekurrenzen der Form
⎛N⎞
T ( n) = 2 ⋅ T ⎜ ⎟ + Θ(n) berechnen
⎝2⎠
4
n lässt sich ⎣log 2 n ⎦ -mal halbieren. Falls n eine Zweierpotenz ist (d.h. n = 2k), lässt sich n sogar exakt
log 2 n = k oft halbieren. n soll der Einfachheit halber hier eine Zweierpotenz sein.
5
Rekurrenzgleichung: Die Analyse rekursiver Algorithmen führt meistens auf eine sog. Rekurrenzgleichung
3
Algorithmen und Datenstrukturen
Vollständige Induktion
Das Beweisverfahren der vollständigen Induktion ist ein Verfahren, mit dem Aussagen über natürliche
Zahlen bewiesen werden können. Neben Aussagen über natürliche Zahlen können auch damit gut
Aussagen bewiesen werden die
- rekursiv definierte Strukturen und
- abzählbare Strukturen
betreffen.
Grundidee: Eine Aussage ist gültig für alle natürlichen Zahlen n ∈ N , wenn man nachweisen kann:
Die Aussage gilt für die erste natürliche Zahl n = 1 (Induktionsanfang)
Wenn die Aussage für eine natürliche Zahl n gilt, dann gilt sie auch für ihren Nachfolger n+1
(Induktionsschritt)
Einf. Bsp.: S ( n) =
n
1
∑ i = 1 + 2 + 3 + ... + n = 2 ⋅ n ⋅ (n + 1)
i =1
Beweis:
Induktionsanfang:
1
⋅ 1 ⋅ (1 + 1) = 1
2
Induktionsschritt:
Induktionsvoraussetzung:
1
⋅ k ⋅ (k + 1)
2
1
⋅ (k + 1) ⋅ (k + ) 2
2
k +1
k
1
1
1
i
=
i + (k + 1) ) = ⋅ k ⋅ (k + 1) + k + 1 = ⋅ (k 2 + k ) + (2k + 2)
∑
∑
2
2
2
i =1
i =1
1
1
= k 2 + k + 2k + 2 = (k + 2) ⋅ (k + 1)
2
2
Zu zeigen, dass gilt:
(
)
Rekurrenzrelationen 6
Eine Rekurrenzrelation (kurz Rekurrenz) ist eine Methode, eine Funktion durch einen Ausdruck zu
definieren, der die zu definierende Funktion selbst enthält, z.B. Fibonacci-Zahlen 7 .
Wie löst man Rekurrenzgleichungen? Es gibt 2 Verfahren: Substitutionsmethode bzw. Mastertheorem.
Abschätzen von Rekurrenzrelationen
Asymptotische Abschätzung mit dem Master-Theorem
Das Mastertheorem hilft bei der Abschätzung der Rekurrenzen der Form T ( n) = a ⋅ T ( n / b) + f ( n) 8
Master-Theorem
- a ≥ 1 und b > 1 sind Konstanten. f (n) ist eine Finktion und T (n ) ist über den nicht-negativen
ganzen Zahlen durch folgende Rekurrenzgleichung definiert:
T (n) = a ⋅ T (n / b ) + f (n) . Interpretiere
n / b so, dass entweder ⎣n / b ⎦ oder ⎡n / b ⎤
- Dann kann T (n ) folgendermaßen asymptotisch abgeschätzt werden:
⎧ Θ(n logb a )
falls gilt : ∃ε > 0 mit f (n) = O(n logb a −ε )
⎪
T (n) = ⎨ Θ n logb a ⋅ log n
falls gilt : f (n) = Θ(n logb a )
⎪Θ( f (n))
falls : ∃ε > 0 mit f (n) = Ω(n logb a +ε ) ∧ ∃c < 1 : ∀n > n0 : a ⋅ f (n / b) ≤ c ⋅ f (n)
⎩
(
)
6
Rekurrenzrelationen sind ein wichtiges Hilfsmittel bei der Analyse rekursiv formulierter Algorithmen
vgl. Skriptum 1.2.7.1, 3.2.3
8 Solche Rekurrenzen treten oft bei der Analyse sogenannter Divide-and-Conquer-Algorithmen auf.
7
4
Algorithmen und Datenstrukturen
Anwendung des Theorems an einigen Beispielen
1. T ( n) = 9 ⋅ T ( n / 3) + n
a = 9, b = 3, f (n) = n
) mit ε = 1 gilt, kann Fall 1 des Master-Theorems angewendet werden.
log 9
2
Somit gilt: T ( n) = Θ n 3 = Θ(n )
2. T ( n) = T ( 2n / 3) + 1
a = 1, b = 3 / 2
log a
log a
log
1
0
Da n b = n 3 / 2 = n = 1 ist, gilt f ( n) = Θ( n b ) = Θ(1) , und es kommt Fall 2 des Masterlog
1
Theorems zur Anwendung. Somit gilt: T ( n) = Θ( n 3 / 2 log n) = Θ(log n)
3. T ( n) = 3 ⋅ T ( n / 4) + n ⋅ log n
a = 3, b = 4, f ( n) = n log n
log a
log 3
0.379
Es ist n b = n 4 = O ( n
). Somit ist f (n) = Ω(n log 4 3+ε ) mit ε ≈ 0.2 . Weiterhin gilt für
hinreichend große n: a ⋅ f (n) = 3 ⋅ (n / 4) ⋅ log(n / 4) ≤ (3 / 4 )n log n . Fall 3 des Master-Theorems
kann damit angewandt werden: T ( n) = O ( f ( n)) = Θ( n ⋅ log n)
Da f ( n) = O ( n
log 3 9 −ε
(
)
Achtung! Es gibt Fälle, in denen die Struktur der Gleichung zu passen „scheint“, aber kein Fall des
Master-Theorems existiert, für den alle Bedingungen erfüllt sind.
Analyse von Algorithmen über O-Notation
Bestimmen der Laufzeitkomplexität von Algorithmen in O-Notation durch Abschätzung der
Größenordnung mit einfachen Regeln 9 .
for-Schleifen
Aufwand: Laufzeit = max. Laufzeit der inneren Anweisungen * Anzahl der Iterationen
Bsp.: for (i=1; i < n;i++) a[i]=0;
Wenn innere Operation O(1), dann n ⋅ O (1) = O ( n)
geschachtelte for-Schleifen
Bsp.: for (i=1;i<n;i++)
for (j=1;j<n;j++)
k=k+1;
n ⋅ n ⋅ O (1) = O (n 2 )
Sequenz
Bsp.: for (i=1; i < n;i++) a[i]=0;
for (i=1;i<n;i++)
for (j=1;j<n;j++)
a[i]=a[i]+a[j]+i+j;
O (n) + O (n 2 ) = O (n 2 )
if-else-Bedingungen
Laufzeit: Aufwand für Test + max(Aufwand für A1, Aufwand für A2)
Bsp.: if (x > 100) y=x;
else
for (i=1;i<n;i++)
if (a[i]>y) y=a[i];
O (n)
P- vs. NP-Probleme 10
- Grenze zwischen effizient lösbaren (polynomialer Aufwand) und nicht effizient lösbaren
(exponentieller Aufwand) Problemen
9
vgl. 1.2.7
vgl. Skriptum, 1.2.7.3
10
5
Algorithmen und Datenstrukturen
- Problemkasse P: Menge aller Probleme, die mit Hilfe deterministischer Algorithmen in polynomialer
Zeit gelöst werden können.
- Problemklasse NP: Menge aller Probleme, die nur mit Hilfe nichtdeterministischer Algorithmen in
polynomialer Zeit gelöst werden können
-- Nichtdeterminismus: „Raten“ der richtigen Variante bei mehreren Lösungen
-- Umsetzung mit deterministischen Algorithmen: exponentieller Aufwand
NP-Vollständigkeit
- Allgemein P ⊆ NP
- Jedoch offenes Problem, ob sich NP-Probleme nicht doch mit polynomialen Aufwand lösen lassen
(also P=NP)
- Beweisbar: Existenz einer Klasse von verwandten Problemen aus NP mit folgender Eigenschaft:
Falls eines dieser Probleme in polynomialer Zeit mit einem deterministischen Algorithmus
gelöst werden könnte, so ist dies für alle Probleme aus NP möglich.
- Man spricht dann von NP-vollständigen Problemen.
Bsp.
1. TSP-Problem
- Problem der Graphentheorie
- Gegeben: Graph mit n Knoten (Städten) und m Kanten (Straßen, mit Entfernungsangaben
versehen
B
5
3
6
A
C
4
E
7
3
4
4
7
D
1
F
4
5
G
5
H
Gesucht: kürzeste Route, die alle Städte besucht und am Startpunkt zurückkehrt.
2. Rucksack-Problem
Wanderer will seinen Rucksack mit verschiedenen Gegenständen packen (auch Knapsack
problem)
Gegeben: Rucksack mit Kapazität C, n Gegenstände jeweils Gewicht gi und Wert wi
Gesucht: Auswahl der Gegenstände ((Indexierung I ⊆ 1,..., n ), deren Gesamtgewicht die
Kapazität nicht überschreitet (
∑g
i∈I
{
i
}
≤ C ) und die Summe der Werte
∑w
i∈I
6
i
maximal ist
Herunterladen