10.07.2015 Aufrufe

Laufzeitkomplexität und Asymptotische Notation

Laufzeitkomplexität und Asymptotische Notation

Laufzeitkomplexität und Asymptotische Notation

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

1Vorlesung Programmierung II: SS 2004<strong>Laufzeitkomplexität</strong><strong>und</strong><strong>Asymptotische</strong> <strong>Notation</strong>Prof. Dr. Hans-Peter Lenhoflenhof@bioinf.uni-sb.de<strong>Laufzeitkomplexität</strong>2Gegeben ein Problemmit einer bestimmten Eingabegröße, z.B.Problem: Man sortiere n vorgegebene ganze Zahlen.Zunächst entwickelt maneffiziente Rechenverfahren (Algorithmen)zur Lösung des Problems.Dann erst implementiert man einen effizientenAlgorithmus für das Problem.1


Der Ursprung des Wortes "Algorithmus"3Historische Herkunft des Begriffs AlgorithmusDas Wort Algorithmus geht auf die lateinische Fassung eines arabischen Namenszurück. Dieser gehörte dem Gelehrten Al-Chwarizmi, der seine mathematischenWerke im 9. Jahrh<strong>und</strong>ert am Hofe des Kalifen Al-Ma'mun in Bagdad schrieb. Einesvon ihnen hieß Hisab al-gabr wal-muqabala, d.h. Rechenverfahren durch Ergänzen<strong>und</strong> Ausgleichen. Das Wort Algebra stammt aus diesem Titel <strong>und</strong> ist offenbar auchhistorisch mit dem Lösen von Gleichungen verb<strong>und</strong>en. In Spanien tauchte der Namedes Verfassers r<strong>und</strong> drei Jahrh<strong>und</strong>erte später in einer lateinischen Bearbeitungseiner Bücher auf. Diese beginnt mit den Worten:Dixit Algoritmi ... [Es sprach Algoritmi ...]Im Laufe der Zeit verband man die daraus entstandene Verballhornung'Algorithmus‚ ganz allgemein mit mechanisch ausführbaren Rechenverfahren.<strong>Laufzeitkomplexität</strong>4Die Untersuchung der Effizienz von Algorithmenist eine zentrale Aufgabe der Informatik.schnelle <strong>und</strong> stabile AlgorithmenWir benötigen Verfahren zur Untersuchungder Laufzeiten von Algorithmen.2


<strong>Laufzeitkomplexität</strong>5Die Laufzeit ist in der Regelabhängig von der Größe der Eingabe .Die Größe des Problems wird meistdurch eine ganze Zahl n beschrieben.Wir diskutieren das Laufzeitverhalteneines Algorithmus als eine Funktion in/von n.Beispiel: Schuladdition6Problem: Gegeben zwei beliebige positive ganze Zahlen a <strong>und</strong> b.Berechne die Summe der Zahlen a <strong>und</strong> b.Beispielfür einen einfachen Algorithmus zur Lösung des Problems:Schuladdition:1 3 5 66 5 5 60 1 1______7 9 1 2 Konkrete Instanz des ProblemsEingabegröße: n = max { #Ziffern(a), #Ziffern(b) }3


Beispiel: Schuladdition939007390074507,947Г.4389 39007 ,intn = (a.digits() < this->digits() ? this->digits():a.digits());Integer sum(n+1); // Variable für die Summeunsigned int carry = 0; // Variable für den Übertrag}for (int i=0; idigits() ? this->digits():a.digits());Integer sum(n+1); // Variable für die Summeunsigned int carry = 0; // Variable für den Übertrag}for (int i=0; i < n ; i++){sum[i] = primitive_add(a[i],(*this)[i], carry);}sum[n] = carry;return sum;1 3 5 66 5 5 60 1 1 0______7 9 1 2„Größenordnung“ der Laufzeit wird bestimmt durch (ist proportionalzur) Zahl der primitiven Operationen.Laufzeit ≤ c * #primitive Operationen = c * n5


Der Schulmultiplikationsalgorithmus39007390074507,947.4389 39007 ,int n = this->digits(), m = a.digits();Integer p;for (int i = 0; i < m ; i++){ // multipliziere (*this) mit der i-ten Ziffer von ap = p + (((*this) * a[i])


Laufzeit als eine Funktion der Größe der Eingabe13– Primitive Operationen werden definiert (eine präzisere Definitionvon primitiven Operationen wird folgen).– Jede primitive Operation wird mit einer Zeiteinheit (1U) bewertet.– D.h., Unterschiede in den Rechenzeiten bedingt durchunterschiedliche Hardware/Compiler werden nicht berücksichtigt.– Laufzeit = Zahl der primitiven Operationen= Funktion der Eingabegröße n– Meist kann man nur eine obere Schranke für die Laufzeitangeben (Worst-Case-Analyse) (siehe Schulmultiplikation).– Diese obere Schranke sollte so “scharf” wie möglich sein.– “Größenordnung” der Laufzeit?RAM oder Random Access Machine14Wir definieren uns ein einfaches Rechnermodell, dass es uns erlaubt,die Ressourcen, welche von einem Algorithmus benötigt werden, abzuschätzen.RAM oder Random Access Machine1. Die RAM hat eine unendliche Folge von Registern oderSpeicherzellen.2. Die folgenden Operationen sind primitive Operationen,d.h., sie können in konstanter Zeit durchgeführt werden:• Lese- oder Schreibzugriff auf jedes Register• Additionen, Subtraktionen, Multiplikationen, Divisionen voneinfachen Datentypen für Zahlen (int, float, usw.)• Deklarationen von einfachen Datentypen (short, int, long,float, double, char, bool, usw.)• Zuweisungen {=} für einfache Datentypen• Sprunganweisungen („goto“), z.B., in if-Anweisung• Vergleiche {==, !=, < , > , >= ,


RAM oder Random Access Machine15Annahme:Primitive Operationen können auf einer RAM inkonstanter Zeit ausgeführt werden.Um die Rechenzeit eines Algorithmus für eine konkreteInstanz eines Problems abzuschätzen, müssen wir dieZeiten der primitiven Operationen aufsummieren.Die Rechenzeit eines Algorithmus kann als eine Funktionder Eingabegröße (Problemgröße) angegeben werden.F+= { f : N → R0}ist die Menge aller Funktionen, die Rechenzeiten (bzgl.einer Eingabegröße n) darstellen können.RAM oder Random Access Machine16Wir üben jetzt das Abschätzen von Rechenzeiten• Jeder Operator (für einen Gr<strong>und</strong>datentyp) benötigtkonstante Zeit.• Eine Deklaration/Definition eines Gr<strong>und</strong>datentypsbenötigt auch konstante Zeit.• Reservieren wir Speicherplatz für „größere“ Objekte,z.B. einen Vektorvector v(n);so zählen wir hierfür cn Zeiteinheiten (≈ Größe).8


RAM oder Random Access Machine17Beispiel: Skalarprodukt von Vektorenint i, n;float p = 0.0;cin >> n;vector v1(n), v2(n);for (i = 0; i < n ; i++) cin >> v1[i] >> v2[i];for (i=0; i < n ; i++) p += v1[i] * v2[i];cout =0)&&(key < v[j]); j--) v[j+1] = v[j]; // c 4 Z?v[j+1] = key;// c 5 n-1}}Im schlimmsten Fall (worst case) gilt:n= ∑ − 111Z i = n(n −1)=1 n 2 ni=12 2− 2c 2 c4f ( n)≤4 n + ( c3+ c5− ) n + ( c1+ c2− c5−3)22cf ( n)≤ cnFür eine geeignet gewählte Konstante c gilt:29


<strong>Asymptotische</strong> <strong>Notation</strong>19Frage: Gegeben zwei Algorithmen mit Laufzeiten f(n) <strong>und</strong> g(n).Welcher Algorithmus ist schneller (effizienter)?Unser Interesse gilt dem Laufzeitverhalten für großeEingaben n, wenn n sozusagen gegen ∞ geht.Frage: Wann betrachten wir zwei Algorithmen als „gleich“ effizient?Man beachte hierbei, dass „Konstanten“ eine untergeordneteRolle spielen <strong>und</strong> „vernachlässigt“ werdenkönnen.<strong>Asymptotische</strong> <strong>Notation</strong>201. Versuch: Definition von „gleich effizient“: Additive KonstanteDie Laufzeiten der beiden Algorithmen unterscheiden sich fürhinreichend große Eingabegrößen n höchstens um eine „additive“Konstante c > 0:f ( n)− g(n)≤ c ∀n ≥ n0Problem mit dieser Definition:f ( n)= 2ng ( n)= nDie obigen Laufzeiten sind eigentlich gleich gut (effizient).Nach der obigen Definition sind f(n) <strong>und</strong> g(n) jedoch nichtin der gleichen „Effizienzklasse“.10


<strong>Asymptotische</strong> <strong>Notation</strong>212. Versuch: Definition von „gleich effizient“: MultiplikativeKonstanteDie Laufzeiten der beiden Algorithmen unterscheiden sich fürhinreichend große Eingabegrößen n höchstens um eine„multiplikative“ Konstante c > 0:f ( n)g(n)≤ c∀n ≥ n 0Problem mit dieser Definition:f ( n)= 10g ( n)= n2Die beiden Funktionen sind nicht gleich effizient, erfüllenaber die Bedingungen der obige Definition!<strong>Asymptotische</strong> <strong>Notation</strong>22Definition von „gleich effizient“: Multiplikative KonstanteFür hinreichend große Eingabegrößen n existieren zweiKonstanten c 1 > 0 <strong>und</strong> c 2 > 0, so dass gilt:c1f ( n)g(n)∀n ≥ n≤ ≤ c20cn)≤ f ( n)≤ c g() ∀n ≥ n01g( 2nGegeben eine Funktion (Laufzeit) g(n). Die Menge allerFunktionen, die die gleiche Effizienz wie g(n) besitzen,können wir wie folgt definieren:(lies: „Theta-von-g“)Θ( g)= { f ∈ F | ∃c1,c2> 0 ∧ ∃n0∈ N : ∀n≥ n0: c1g( n)≤ f ( n)≤ c2g(n)}11


<strong>Asymptotische</strong> <strong>Notation</strong>c 2g(n)f(n)c 1g(n)23f ( n)∈Θ(g)(lies: „Theta-von-g“)n 0nΘ( g)= { f ∈ F | ∃c1,c2> 0 ∧ ∃n0∈ N : ∀n≥ n0: c1g( n)≤ f ( n)≤ c2g(n)}Intuitiv ist f ∈ Θ(g), falls f in der gleichen Größenordnung wie g ist,d.h., f <strong>und</strong> g sind gleich oder ähnlich effizient<strong>Asymptotische</strong> <strong>Notation</strong>24Die asymptotische <strong>Notation</strong> dient zur Klassifizierung <strong>und</strong> zumVergleich von Funktionen nach ihren Zuwachsraten:Sei+F = { f : N → R0}O( g)= { f ∈ F | ∃c> 0 ∧ ∃n0 ∈ N : ∀n≥ n0: f ( n)≤ cg(n)}(„O-von-g“)cg(n)f(n)f ( n)∈O(g)n 0n12


<strong>Asymptotische</strong> <strong>Notation</strong>25Die asymptotische <strong>Notation</strong> dient zur Klassifizierung <strong>und</strong> zumVergleich von Funktionen nach ihren Zuwachsraten:+Sei F = f : N → R } die Menge aller Funktionen von N nach R 0+.{0Definition [1]:Für g ∈ F istΘ( g)= { f ∈ F | ∃c1,c2> 0 ∧ ∃n0∈ N : ∀n≥ n0: c1g( n)≤ f ( n)≤ c2g(n)}O( g)= { f ∈ F | ∃c> 0 ∧ ∃n0 ∈ N : ∀n≥ n0: f ( n)≤ cg(n)}Ω( g)= { f ∈ F | ∃c> 0 ∧ ∃n0 ∈ N : ∀n≥ n0: f ( n)≥ cg(n)}o ( g)= { f ∈ F | ∀c> 0 ∧ ∃n0 ∈ N : ∀n≥ n0: f ( n)< cg(n)}ω( g ) = { f ∈ F | ∀c> 0 ∧ ∃n0 ∈ N : ∀n≥ n0: f ( n)> cg(n)}<strong>Asymptotische</strong> <strong>Notation</strong>26Stark vereinfacht können wir das asymptotische Wachstumsverhaltender verschiedenen Funktionenklassen wie folgt interpretieren:f ∈ O(g)≈f≤ g[„f wächst nicht schneller als g“]f ∈ Ω(g)≈f≥ gf ∈ Θ(g)≈ f = gf ∈ o(g)≈ f < gf ∈ ω( g)≈ f > gBeispiel: g(n) = n 2f(n) = 3n 2 +7n+12 ≤ 3n 2 +7n 2 +12n 2 ≤ 22n 2 ≤ c g(n)f ∈ O(g)f(n) = 3n 2 +7n+12 ≥ n 2 = g(n)f ∈Θ(g)13


<strong>Asymptotische</strong> <strong>Notation</strong>Satz [1]: Transitivität:f ( n)∈ O(g(n))∧ g( n)∈O(h(n))⇒ f ( n)∈O(h(n))27Beweis:f ( n)∈O(g(n))⇔ c > 0 n > 0g( n)∈O(h(n))⇔Seic = c f* c g∃ f∃cg> 0∃ f∃ngf ( n)≤ c g(n)≤ c c h(n)≤ ch(n)f⇒ ∃c > 0 00>⇔ f ( n)∈O(h(n))f> 0∀ n ≥ nff ( n)≤ cfg(n)∀ n ≥ ngg( n)≤ cgh(n)<strong>und</strong> n0= max{ n f, ng}dann gilt für alle n ≥ n0g∃n so dass ∀n ≥ n0gilt: f ( n)≤ ch(n)Satz [2]: Reflexivität:f ( n)∈O(f ( n))<strong>Asymptotische</strong> <strong>Notation</strong>Satz [3]: Symmetrie:f ( n)∈ Θ(g(n))dann <strong>und</strong> nur dann g( n)∈ Θ(f ( n))28Beweis: Übung.Ferner zeige man, dass die Symmetrie-Aussage nicht für „O“(falls Θ oben durch O ersetzt wird) gilt.Lemma [1]:[a] O( g(n))+ O(h(n))⊆ O(max{g(n),h(n)})[b] c* O(g(n))⊆ O(g(n))[c] O( g(n))O(h(n))⊆ O(g(n)h(n))Beweis:Wir beweisen hier die Aussage [a] von Lemma (3).Die Beweise von Aussage [b] <strong>und</strong> [c] sind Übungen.Die Aussage [a] kann wie folgt umformuliert werden:nächste Seite14


<strong>Asymptotische</strong> <strong>Notation</strong>29[a]O( g)+ O(h)⊆ O(max{g,h})⇔ ∀ f ∈O( g)∧ ∀f∈O(h): f ( n)+ f ( n)∈O(max{g,h})gg∀f∈Og) : ∃c> 0 ∧ ∃nhh( so dassf g f g∀f∈Oh) : ∃c> 0 ∧ ∃n( so dassf h f hgh∀n ≥ n fgilt:gfg( n)≤ cfg(n)g∀n ≥ n fhgilt: f ( n)≤ c h(n)Wir betrachten nun die Summe zweier beliebiger Funktionen f g <strong>und</strong> f h :∀n ≥max{ n f, ngfh}gilt:fg( n)+ fh(n)≤ cfg( n)+ c h(n)gf≤ max{ c , c }( g(n)h(n))hf g f+h≤ max{ c , c }(2 max{ g(n),h(n)})⇔ f ( n)+ f ( n)∈O(max{g,h})gh≤ max{ 2cf g fh,2cf g fhhfh}max{ g(n),h(n)}<strong>Asymptotische</strong> <strong>Notation</strong>30• Gegeben ein Algorithmus mit Laufzeit f(n).• Meist können wir die Laufzeit im Worst-Case nur nach obendurch eine Funktion g(n) abschätzen, d.h., f(n) ∈ O(g(n)).• Oft ist g(n) ein Polynom in der Variablen n:• Dag ( n ) =n→∞folgt, dass g(n)∈Θ(n k ) ⇒ g(n)∈ O(n k ) <strong>und</strong> somitk∑i=0c i ng(n)lim = cknikkkf ( n)∈O(g(n))∧ g(n)∈O(n ) Satz1 f ( n)∈O(n )15


<strong>Asymptotische</strong> <strong>Notation</strong>31• Gegeben ein Algorithmus mit Laufzeit f(n).• Meist können wir die Laufzeit im Worst-Case nur nach obendurch eine Funktion g(n) abschätzen, d.h., f(n) ∈ O(g(n)).• Ist g(n) die Summe von verschiedenen Funktionen,g(n)=k∑i=0g ( n)iso bestimmt die am „schnellsten wachsende“ Funktion g j (n)die Größenordung von g(n) (siehe Lemma [1] a):f ( n)∈O(g(n))∧ g(n)∈O(g ( n))Satz [1] f ( n)∈O(gj( n))Die Anzahl k der Summanden muss hierbei eineKonstante sein <strong>und</strong> darf nicht von n abhängen.jEinige vereinfachende Schreibweisen:<strong>Asymptotische</strong> <strong>Notation</strong>32g : N R+→ 0g ( n)= nO ( g(n))= O(n)g =x( n)nxO ( g(n))= O(n )g ( n)= log( n)O ( g(n))= O(log(n))g ( n)= nlog(n)O ( g(n))= O(n log( n))usw.Anstelle der Schreibweisef ( n)∈O(g(n))findet man in der Literatur oft auchf ( n)≤ O(g(n))oder (ähnlich „schlampig“)f ( n)= O(g(n))f n = n + n + = O n = O n223Beispiel: ( ) 3 7 12 ( ) ( )f ( n)= 3n2+ 7n+ 12∈O(n2) ⊂ O(n3)16


<strong>Asymptotische</strong> <strong>Notation</strong>Hinter der Benutzung der asymptotischen <strong>Notation</strong> steht die impliziteAnnahme, dass ein Algorithmus immer dann besser als ein andererAlgorithmus ist, wenn die asymptotische Zuwachsrate seiner Laufzeit(bzw. seines Speicherplatzbedarfs) kleiner als die des anderenAlgorithmus ist.33Laufzeit von Algorithmus 1:100f1(n)= 10 n ∈O(n)Laufzeit von Algorithmus 2:2f2(n)= n ∈O(n2)Für alle n mitf1( n)= 10100100n < 10ngilt jedoch: Für alle realistischen Eingabegrößenhat der Algorithmus 2= f 2(n die bessere Laufzeit.2> n )Vergleiche von Ressourcenanforderungen (Laufzeit <strong>und</strong> Speicherplatz)mittels asymptotischen Größenordnungen (O-<strong>Notation</strong>) sind nur unterbestimmten Voraussetzungen sinnvoll („u.a. Voraussetzungen über dieKonstanten“).<strong>Asymptotische</strong> <strong>Notation</strong>34Beispiel:Wir untersuchen einen Algorithmus A <strong>und</strong> erhalten als Laufzeit22f ( n)= 3n+ 15nlogn + n ∈ O ( n)+ O(nlogn)+ O(n ) ⊆ O( n2 )Oft wird dies stark vereinfacht wie folgt geschrieben:223n + 15nlog n + n = O ( n)+ O(nlogn)+ O(n ) = O( n2 )Diese „Gleichungen“ dürfen nur von links nach rechts gelesen werden!Man sagt:„Der Algorithmus hat die Laufzeit (Zeitkomplexität) O(n 2 ).“17


<strong>Asymptotische</strong> <strong>Notation</strong>35Die bekannteste Problemlösestrategie der Informatik ist„Divide&Conquer“ („teile <strong>und</strong> herrsche“).Gegeben zwei n-stellige Zahlena = a na )( −1 0 B( b n −1b0Bb = )Teile a <strong>und</strong> b jeweilsin zwei Hälften:(1)a = ( a n −1a m)(1)b = ( b n −1b m)wobei m = ⎡n / 2⎤BB(0)a = a ma)(−10 B( b m −1b0B(0)b = )(1) (0)Dann gilt: a = a Bm + ab = b(1)Bm +b(0)ab = ( a(1)Bm+ a(0))( b(1)Bm+ b(0)) = a(1)b(1)B2m+(0) (1) (1) (0) m (0) (0)( a b + a b ) B + a bHieraus folgt:Die Multiplikation zweier n-stelliger Zahlen lässt sich also auf vierMultiplikation zweier höchstens ⎡n/2⎤-stelliger Zahlen zurückführen(plus Shift-Operationen).<strong>Asymptotische</strong> <strong>Notation</strong>36ab = ( a(1)Bm+ a(0))( b(1)Bk+ b(0)) = a(1)b(1)Bm+k+ a390074507,947.4389 39007 ,.4389 39007 -Integer a0 = a, a1 = 0, b0 = b, b1 = 0;int n = a.digits(), l = b.digits();(0)b(1)Bm+ a// falls a <strong>und</strong> b einstellig, tut es eine primitive Multiplikationif (n == 1 && l == 1) return primitive_mult(a[0],b[0]);(1)b(0)Bk+ a(0)b(0)int m = n/2, k = l/2;if ( m > 0 ) {a1 = a >> m;a0 = a - (a1 0 ) {b1 = b >> k;b0 = b - (b1


<strong>Asymptotische</strong> <strong>Notation</strong>37ab = ( a(1)Bm+ a(0))( b(1)Bk+ b(0)) = a(1)b(1)Bm+k+ a(1)b(0)Bm+ a(0)b(1)Bk+ a(0)b(0)}3900755555,-5,-5,-5,-return (p1 + (p2

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!