Aufwand Algorithmen und Datenstrukturen I Aspekte von Algorithmen: Aufwand D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg c Winter 2009/10, 26. Oktober 2009, 2009/10 D.Rösner D. Rösner AuD I 2009/10 . . . 1 Aufwand Gliederung 1 Aufwand Einleitung O-Notation Listenfunktionen D. Rösner AuD I 2009/10 . . . 2 Aufwand Einleitung O-Notation Listenfunktionen Aufwandbetrachtungen: für ein Problem gibt es oft unterschiedlich aufwendige Lösungen Beispiel: Fibonacci-Zahlen die Folge der Fibonacci-Zahlen ist definiert durch: Anfangswerte: 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 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 I 2009/10 . . . 4 Aufwand Einleitung O-Notation Listenfunktionen Beispiel: Berechnung der Fibonacci-Zahlen die Definition der Fibonacci-Zahlen lässt sich direkt in einen rekursiven Algorithmus umsetzen in Haskell: Variante mit Pattern matching fib :: Int -> Int fib 0 = 1 fib 1 = 1 fib n = fib (n - 1) + fib (n - 2) D. Rösner AuD I 2009/10 . . . 5 Aufwand Einleitung 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 AuD I 2009/10 . . . 6 Aufwand Einleitung O-Notation Listenfunktionen 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 I 2009/10 . . . 7 Aufwand Einleitung O-Notation Listenfunktionen Beispiel: Berechnung der Fibonacci-Zahlen zusammengefasst: 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 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 D. Rösner AuD I 2009/10 . . . 8 Aufwand Einleitung O-Notation Listenfunktionen Vergleich von Funktionen asymptotischer Vergleich von Funktionen O (sprich: gross-0) für “asymptotisch kleiner als oder gleich“ Seien im folgenden f und g Funktionen von den natürlichen Zahlen in die nichtnegativen reellen Zahlen. Definition (vgl. [GT01], 3.6): 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 I 2009/10 . . . 10 Aufwand Einleitung O-Notation Listenfunktionen Vergleich von Funktionen Ω (sprich: gross-0mega) für “asymptotisch grösser als oder gleich“ 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 I 2009/10 . . . 11 Aufwand Einleitung O-Notation Listenfunktionen Vergleich von Funktionen Θ (sprich: gross-Theta) für “asymptotisch gleich“ Definition (vgl. [GT01], 3.6): 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 AuD I 2009/10 . . . 12 Aufwand Einleitung O-Notation Listenfunktionen 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 I 2009/10 . . . 13 Aufwand Einleitung O-Notation Listenfunktionen Vergleich von Funktionen 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 I 2009/10 . . . 14 Aufwand Einleitung O-Notation Listenfunktionen Aufwand bei Listenfunktionen Zugriff auf das erste Listenelement (den Listenkopf) im Prelude definiert als: head head (x:_) :: [a] -> a = x der Aufwand ist unabhängig von der Länge der Liste konstant, d.h. O(1) D. Rösner AuD I 2009/10 . . . 16 Aufwand Einleitung O-Notation Listenfunktionen Aufwand bei Listenfunktionen Test, ob ein Element in einer Liste der Länge n enthalten elem elem _ [] elem y (x:xs) :: a -> [a] -> Bool = False = if y == x then True else elem y xs günstigster Fall: y ist gleich dem ersten Listenelement 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 bezogen auf n, d.h. O(n) D. Rösner AuD I 2009/10 . . . 17 Aufwand Einleitung 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] -> [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 m.a.W.: Aufwand ist quadratisch, d.h. O(n2 ) D. Rösner AuD I 2009/10 . . . 18 Aufwand Einleitung O-Notation Listenfunktionen Literatur: I 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. D. Rösner AuD I 2009/10 . . . 19