Lektion 1.1

Laufzeit messen: Operationen zählen und O-Notation

30 min Lesezeit

Du hast zwei Programme, die dasselbe Problem lösen. Welches ist besser? Die Stoppuhr ist eine schlechte Antwort: Das Ergebnis hängt vom Rechner, vom Compiler und davon ab, was nebenbei läuft. Außerdem sagt eine Messung bei 10001000 Eingaben nichts darüber, was bei einer Million passiert.

Die Informatik misst deshalb nicht Sekunden, sondern zählt Grundoperationen (Vergleiche, Zuweisungen, Rechenschritte) in Abhängigkeit von der Eingabegröße nn. Und weil es bei großen nn nur auf die Wachstumsart ankommt, vergisst man Konstanten und Nebenglieder. Das Ergebnis ist die O-Notation: eine grobe, aber maschinenunabhängige Sprache für die Frage „Wie schnell wächst der Aufwand, wenn die Eingabe größer wird?"

Beispiel

Operationen in Schleifen zählen

Betrachte zwei verschachtelte Schleifen, wie sie in Sortieralgorithmen vorkommen: Die äußere Schleife läuft für i=0,…,n−1i = 0, \dots, n-1, die innere für j=0,…,i−1j = 0, \dots, i-1, und im Inneren steht ein Vergleich. Wie oft wird verglichen?

Für i=0i = 0 gar nicht, für i=1i = 1 einmal, für i=2i = 2 zweimal, und so weiter bis i=n−1i = n-1 mit n−1n-1 Vergleichen. Die Summe ist die Gaußsche Summenformel:

0+1+2+⋯+(n−1)=n(n−1)20 + 1 + 2 + \dots + (n-1) = \frac{n(n-1)}{2}

Für n=10n = 10 sind es 4545 Vergleiche, für n=1000n = 1000 schon 499 500499\,500, und für n=106n = 10^6 etwa 5⋅10115 \cdot 10^{11}. Verzehnfachst du nn, wächst die Zahl der Vergleiche etwa um den Faktor 100100. Das ist die Signatur eines quadratischen Aufwands.

Definition

O-Notation (obere Schranke)

Seien ff und gg Funktionen von den natürlichen Zahlen in die nichtnegativen reellen Zahlen. Man sagt ff liegt in O(g)O(g), wenn es eine Konstante c>0c > 0 und eine Schwelle n0n_0 gibt, sodass ab dieser Schwelle ff höchstens so groß wie cc mal gg ist.

Die Idee: Ab einer gewissen Eingabegröße wächst ff nicht schneller als ein konstantes Vielfaches von gg. Konstante Faktoren und Glieder niedrigerer Ordnung spielen dabei keine Rolle. Man schreibt oft ungenau f=O(g)f = O(g) statt f∈O(g)f \in O(g).

f∈O(g)  :⟺  ∃ c>0, n0: ∀n≥n0: f(n)≤c⋅g(n)f \in O(g) \;:\Longleftrightarrow\; \exists\, c > 0,\ n_0:\ \forall n \ge n_0:\ f(n) \le c\cdot g(n)
Beispiel

Nachweis: 3n2+5n∈O(n2)3n^2 + 5n \in O(n^2)

Wir wählen c=4c = 4 und n0=5n_0 = 5. Für alle n≥5n \ge 5 gilt 5n≤n25n \le n^2 (denn 5≤n5 \le n), also:

3n2+5n  ≤  3n2+n2  =  4n23n^2 + 5n \;\le\; 3n^2 + n^2 \;=\; 4n^2

Damit ist die Definition erfüllt. Ebenso gilt 100n+n2∈O(n2)100n + n^2 \in O(n^2), denn für große nn dominiert das quadratische Glied. Umgekehrt ist n2∉O(n)n^2 \notin O(n): Egal wie groß cc ist, ab n>cn > c gilt n2>c⋅nn^2 > c \cdot n.

Definition

Wichtige Wachstumsklassen

Diese Klassen begegnen dir in jedem Algorithmus-Lehrbuch, geordnet vom langsamsten zum schnellsten Wachstum:

  • O(1)O(1) konstant: ein Arrayzugriff.
  • O(log⁡n)O(\log n) logarithmisch: binäre Suche; jeder Schritt halbiert das Problem.
  • O(n)O(n) linear: ein Durchlauf durch die Daten.
  • O(nlog⁡n)O(n \log n) linearithmisch: gute Sortierverfahren wie Mergesort.
  • O(n2)O(n^2) quadratisch: zwei verschachtelte Schleifen, einfache Sortierverfahren.
  • O(2n)O(2^n) exponentiell: alle Teilmengen durchprobieren.

Mit dem Logarithmus ist in der Informatik fast immer der Logarithmus zur Basis 22 gemeint. Die Basis ändert nur einen konstanten Faktor und ist in der O-Notation egal.

1  ≺  log⁡n  ≺  n  ≺  nlog⁡n  ≺  n2  ≺  2n1 \;\prec\; \log n \;\prec\; n \;\prec\; n\log n \;\prec\; n^2 \;\prec\; 2^n

Zusammenfassung

  • Aufwand wird als Anzahl der Grundoperationen in Abhängigkeit von der Eingabegröße nn angegeben, nicht in Sekunden.

  • Die O-Notation ignoriert konstante Faktoren und Glieder niedrigerer Ordnung: f∈O(g)f \in O(g), wenn f(n)≤c⋅g(n)f(n) \le c\cdot g(n) ab einem n0n_0.

  • Zwei verschachtelte Schleifen mit Dreiecksform liefern n(n−1)2∈O(n2)\frac{n(n-1)}{2} \in O(n^2).

  • Rangfolge: 1≺log⁡n≺n≺nlog⁡n≺n2≺2n1 \prec \log n \prec n \prec n\log n \prec n^2 \prec 2^n.

  • Meist wird die Worst-Case-Laufzeit angegeben, weil sie eine Garantie ist.

Übungen

Aufgabe 1Numerisch

Eine äußere Schleife läuft für i=0,…,n−1i = 0, \dots, n-1, die innere für j=0,…,i−1j = 0, \dots, i-1. Wie oft wird der Rumpf der inneren Schleife für n=10n = 10 ausgeführt?

Aufgabe 2Multiple Choice

Welche der folgenden Aussagen ist richtig?

Aufgabe 3Numerisch

Ein Verfahren braucht ungefähr n⋅log⁡2nn \cdot \log_2 n Schritte. Wie viele sind es für n=1024n = 1024?

Aufgabe 4Freitext

Zeige mit der Definition der O-Notation, dass 5n+20∈O(n)5n + 20 \in O(n) gilt. Gib cc und n0n_0 an.