Logo Logo
InfoHome Themen Projekte Links Software
Themen
JavaHamster
BlueJ
Java
Sprachelemente
Abstrakte Datentypen
Swing
Sortieren
Binäre Suche
InsertionSort
SelectionSort
BubbleSort
ShakerSort
Quicksort
MergeSort
Komplexität
HTML
XHTML
CSS
XML
Datenbanken
MySQL
Theoretische Informatik
PHP
Kara
Lego-Roboter
Algorithmen

Komplexität von Algorithmen - die O-Notation

Die O-Notation (engl. Big-Oh-Notation) stellt ein Hilfsmittel zur Untersuchung der Laufzeit eines Algorithmus dar.

Historisches

Eingeführt wurde die Symbolik der O-Notation durch den englischen Mathematiker Paul Bachmann (1837-1920) im Jahr 1894 in seinem Werk "Analytische Zahlentheorie". Später machte der Zahlentheoretiker Paul Landau (1877-1938) davon Gebrauch, weshalb die O-Notation gern auch als Schreibweise Landau'scher Symbole bezeichnet wird.

Zielsetzung

Das Ziel ist die Untersuchung der Laufzeitkomplexität von Algorithmen. Hierbei verfolgt man im Allgemeinen drei Grundgedanken:

  1. Die Laufzeit eines Algorithmus soll in Abhängigkeit von der Anzahl an Eingabedaten n des Algorithmus untersucht werden. Es soll eine Funktion f in Abhängigkeit von der Anzahl der Eingabewerte n gefunden werden, welche die Laufzeit des Algorithmus wiedergibt: f(n).
  2. Die angegebene Funktion f(n) soll unabhängig von rechnerspezifischen Details (tatsächlicher zeitlicher Aufwand) sein, daher ist von konstanten Faktoren c zu abstrahieren. Mit Laufzeit ist hier also nicht die zeitliche Dauer gemeint, die ein Algorithmus bis zu seiner Terminierung benötigt, sondern die Anzahl an Basis-Operationen, die der Algorithmus in Abhängigkeit von der Anzahl an Eingabedaten ausführen muss.
  3. Die Funktion, die mittels O-Notation zur Kennzeichnung der Laufzeit angegeben wird, stellt - multipliziert mit einem rechnerabhängigen Faktor - eine obere Schranke für die tatsächliche Laufzeitfunktion dar, wenn die Anzahl der Eingabewerte einmal einen bestimmten Wert überschritten haben. Also untersucht man mit der O-Notation immer die Laufzeit im ungünstigsten Fall, im "worst case". Meist sucht man nicht irgendeine Funktion, welche (wiederum multipliziert mit der rechnerabhängigen Konstante) die tatsächliche Laufzeit majorisiert, sondern die kleinste. So würde eine Funktion g(n), zu welcher n2 eine obere Schranke bildet, ebenfalls von n3 majorisiert werden, dies ist jedoch unerheblich, da n2 eine "kleinere" Majorante zu g(n) darstellt, als n3. Allgemein sucht man eine Funktion f(n), für welche gilt: "c * f(n) ≥ g(n)", wobei g(n) die eigentliche Laufzeit und c die systemabhängige Konstante bezeichnet. Ist c * f(n) die kleinste Majorante von g(n), so kann dieser Term auch "Asymptote" von g(n) genannt werden, womit die Angabe der Laufzeit mittels O-Notation oft auch als "asymptotische Laufzeitkomplexität" bezeichnet wird.

Definition

Eine mögliche mathematische Definition und zugleich auch die gebräuchlichste ist folgende:

Gesprochen würde dies heissen: "O(f(n)) ist die Menge aller Funktionen g(n), für die es zwei Konstanten n0 und c gibt, so dass für alle n ≥ n0 gilt: g(n) ≤ c * f(n)".

Komlexitätsklassen

Eine kurze Zusammenfassung der wichtigsten Laufzeitkomplexitäten und in welchen praktischen Anwendungen man sie wiederfinden kann:

  • logarithmische Komplexität: O(log(n)); kommt z.B. bei der "binären Suche" vor sowie bei allen "square-and-multiply"-Verfahren; diese Komplexität ist sehr günstig, da die Laufzeit noch nicht einmal linear wächst, beispielsweise kommt es durch Quadrieren von n gerade einmal zu einer Verdopplung der Laufzeit
  • lineare Komplexität: O(n); z.B. bei der Suche in einem unsortierten Feld; diese Komplexität sollte das primäre Ziel eines Algorithmenentwurfs sein, ist aber nur selten erreichbar
  • n*log(n)-Komplexität: O(n*log(n)); die Laufzeit einiger der schnellsten Sortieralgorithmen wird dadurch charakterisiert (z.B. Mergesort); ist noch sehr günstig, wenn auch nicht mehr linear
  • quadratische Komplexität: O(n2); in der Praxis charakterisierend für den Bubblesort-Algorithmus oder z.B. die Multiplikation einer Matrix mit einem Vektor; ist nicht mehr so günstig, da eine Verdopplung der Eingabedaten eine Vervierfachung der Laufzeit nach sich zieht, jedoch immernoch vertretbar
  • kubische Komplexität: O(n3); z.B. bei der Multiplikation zweier Matrizen; ist noch ungünstiger
  • exponentielle Komplexität: O(cn); katastrophal schon für kleine n
  • gemäß Fakultätsfunktion wachsende Komplexität: O(n!); katastrophal schon für kleine n
  • superexponentielle Komplexität: O(nn); katastrophal schon für kleine n

Quelle: linux-related.de

Komplexität von vergleichsbasierten Sortierverfahren

 Sortierverfahren  Best-Case  Average-Case  Worst-Case  stabil  rekursiv  in-place
 SelectionSort  O(n2)  O(n2)  O(n2)  nein  nein  ja
 InsertionSort  O(n)  O(n2)  O(n2)  ja  nein  ja
 BubbleSort  O(n)  O(n2)  O(n2)  ja  nein  ja
 Quicksort  O(n * log(n))  O(n * log(n))  O(n2)  nein  ja  ja
 MergeSort  O(n * log(n))  O(n * log(n))  O(n * log(n))  ja  ja  nein; zusätzlicher Speicherbedarf: O(n) 

Quelle: de.wikipedia.org

 

» drucken: pdf | html

© 2004-2024 M. Blanke · Ursulaschule · Kleine Domsfreiheit 11-18 · 49074 Osnabrück