Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: O-Notation Listenfunktionen Gliederung Algorithmen und Datenstrukturen – Einführung Weitere Aspekte von Algorithmen D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg 1 2 3 Aufwandbetrachtungen: O-Notation Listenfunktionen Winter 2008/2009, 3. November 2008 D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: Beispiel: Berechnung der Fibonacci-Zahlen für ein Problem gibt es oft unterschiedlich aufwendige Lösungen Beispiel: Fibonacci-Zahlen die Folge der Fibonacci-Zahlen ist definiert durch: Anfangswerte: die Definition der Fibonacci-Zahlen lässt sich direkt in einen rekursiven Algorithmus umsetzen in Haskell: Variante mit Pattern matching fib :: Int -> Int fib0 = 1, fib1 = 1 für alle anderen Werte (d.h. für n ≥ 2) gilt die folgende rekursive Definition: fibn = fibn−1 + fibn−2 fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) die Fibonacci-Zahlen wurden von Leonardo von Pisa (ca. 1170 – 1250; genannt Fibonacci) entwickelt, um u.a. die Vermehrung von Kaninchen-Populationen zu beschreiben D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: O-Notation Listenfunktionen Beispiel: Berechnung der Fibonacci-Zahlen die Werte in der Folge wachsen sehr schnell an so ergeben sich die ersten 30 Fibonacci-Zahlen als Main> take 30 [(n, fib n)| n <- [0 ..]] [(0,1),(1,1),(2,2),(3,3),(4,5),(5,8),(6,13),(7,21), (8,34),(9,55),(10,89),(11,144),(12,233),(13,377), (14,610),(15,987),(16,1597),(17,2584),(18,4181), (19,6765),(20,10946),(21,17711),(22,28657),(23,46368), (24,75025),(25,121393),(26,196418),(27,317811), (28,514229),(29,832040)] D. Rösner Beispiel: Berechnung der Fibonacci-Zahlen die direkte Umsetzung der Definition erfordert einen Aufwand, der exponentiell in Abhängigkeit von n anwächst dies ergibt sich aus folgender Abschätzung nach unten für den mindestens erforderlichen Aufwand (hier gemessen in Anzahl von Funktionsaufrufen): wegen fib n = fib (n - 1) + fib (n - 2) : aufwand(fib n) ≥ 2 * aufwand(fib (n - 2)) ≥ 2 * 2 * aufwand(fib (n - 4)) ... für n gerade: ≥ 2(n/2−1) * aufwand(fib 2) = 2n/2 analog für n ungerade: ≥ 2(n−1)/2−1 * aufwand(fib 3) ≥ 2(n−1)/2 D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Beispiel: Berechnung der Fibonacci-Zahlen Vergleich von Funktionen asymptotischer Vergleich von Funktionen zusammengefasst: O (sprich: gross-0) Aufwand für Berechnung von fib n (hier gemessen in Anzahl von Funktionsaufrufen) wächst in Abhängigkeit von n mindestens so stark wie 2(n−1)/2 für “asymptotisch kleiner als oder gleich“ im Kontrast dazu ist der Aufwand für die Berechnung von fastFib n (vgl. letzte Vorlesung und [Tho99], pp. 75) nur eine lineare Funktion von n Definition (vgl. [GT01], 3.6): D. Rösner AuD 2008/2009 . . . Seien im folgenden f und g Funktionen von den natürlichen Zahlen in die nichtnegativen reellen Zahlen. f(n) ist O(g(n)) wenn es eine reelle Konstante c > 0 und eine natürliche Zahl n0 ≥ 1 gibt, so dass f(n) ≤ c g(n) für alle n ≥ n0 D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: O-Notation Listenfunktionen Vergleich von Funktionen Vergleich von Funktionen Θ (sprich: gross-Theta) Ω (sprich: gross-0mega) für “asymptotisch gleich“ für “asymptotisch grösser als oder gleich“ Definition (vgl. [GT01], 3.6): Definition (vgl. [GT01], 3.6): f(n) ist Ω(g(n)) wenn g(n) ist O(f(n)) d.h. es gibt eine reelle Konstante c > 0 und eine natürliche Zahl n0 ≥ 1, so dass f(n) ≥ c g(n) für alle n ≥ n0 D. Rösner AuD 2008/2009 . . . f(n) ist Θ(g(n)) wenn f(n) ist O(g(n)) und f(n) ist Ω(g(n)) m.a.W. es gibt reelle Konstanten c > 0 und d > 0 und eine natürliche Zahl n0 ≥ 1, so dass c g(n) ≤ f(n) ≤ d g(n) für alle n ≥ n0 D. Rösner Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: O-Notation Listenfunktionen Vergleich von Funktionen Vergleich von Funktionen Beispiele (vgl. [GT01], 3.6): 20 n3 + 10 n log n + 5 ist O(n3 ) Begründung: für n ≥ 1 : log n < n n log n < n2 ≤ n3 10 n log n ≤ 10 n3 Damit: 20 n3 + 10 n log n + 5 ≤ 35 n3 D. Rösner AuD 2008/2009 . . . AuD 2008/2009 . . . Beispiele (vgl. [GT01], 3.6): jedes Polynom ak nk + ak −1 nk −1 + . . . + a0 ist O(nk ) 3 log n + log log n ist O(log n) Begründung: für n ≥ 2 : log log n ≤ log n Damit: 3 log n + log log n ≤ 4 log n für n ≥ 2 D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwand bei Listenfunktionen Aufwand bei Listenfunktionen Test, ob ein Element in einer Liste der Länge n enthalten Zugriff auf das erste Listenelement (den Listenkopf) im Prelude definiert als: head :: [a] -> a head (x:_) der Aufwand ist unabhängig von der Länge der Liste konstant, d.h. O(1) elem _ [] elem y (x:xs) = False = if y == x then True else elem y xs schlechtester Fall (sog. “worst case“): y ist überhaupt nicht in der Liste enthalten (oder als letztes Element) Aufwand (hier z.B. Zahl der rekursiven Aufrufe und der Tests auf Gleichheit) ist linear bezeogen auf n, d.h. O(n) D. Rösner AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen AuD 2008/2009 . . . Aufwandbetrachtungen: O-Notation Listenfunktionen Aufwand bei Listenfunktionen Schnittbildung zweier Listen, d.h. Bestimmung derjenigen Elemente, die in beiden Listen enthalten intersect intersect _ [] intersect [] _ intersect (x:xs) y :: a -> [a] -> Bool günstigster Fall: y ist gleich dem ersten Listenelement = x D. Rösner elem :: [a] -> [a] -> [a] = [] = [] = if elem x y then x:(intersect xs y) else (intersect xs y) schlechtester Fall: die Listen haben keine gemeinsamen Elemente mit m = length (x:xs) und n = length y ergeben sich m mal n Tests auf Enthaltensein Literatur: Michael T. Goodrich and Roberto Tamassia. Data Structures and Algorithms in Java. John Wiley & Sons, New York, 2001. ISBN 0-471-38367-8; 2nd edition. Simon Thompson. Haskell - The Craft of Functional Programming. Addison Wesley Longman Ltd., Essex, 1999. 2nd edition, ISBN 0-201-34275-8; Accompanying Web site: http://www.cs.ukc.ac.uk/people/staff/sjt/craft2e. m.a.W.: Aufwand ist quadratisch, d.h. O(n2 ) D. Rösner AuD 2008/2009 . . . D. Rösner AuD 2008/2009 . . .