English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

nu

Gast
1 / ?

Wachstumsraten, nicht absolute Kosten

Groß O: Messen der Geschwindigkeit der Kostenentwicklung

Groß O-Notation misst die Wachstumsrate der Kosten eines Algorithmus - nicht die absoluten Kosten.

Die Frage, die Groß O beantwortet: Verdoppelt sich der Input-Größe N, verdoppelt sich auch die Arbeit? Vierfacht sich die Arbeit? Bleibt sie flach?

Das 'O' steht für 'Ordnungsgroesse'. Das Ausdruck innerhalb der Klammer beschreibt die Form der Wachstumskurve.

Groß O-Wachstumstabelle: Operationen bei N=10, 100 und 1.000 für O(1), O(N) und O(N²)

Schlüsselkomplexitätsklassen:

- O(1) - konstant: Die Kosten entwickeln sich nicht. Beispiel: Suchen eines Wertes durch Index in einem Array. Ob das Array 10 Elemente oder 10 Millionen hat, bleibt eine einzelne Suche.

- O(N) - linear: Die Kosten wachsen mit dem Input. Beispiel: Lesen aller Elemente in einer Liste einmal. Doppelt die Liste, verdoppelt sich die Anzahl der Lesen.

- O(N²) - quadratisch: Die Kosten wachsen als Quadrat des Inputs. Beispiel: Vergleichen aller Elemente miteinander. Verdoppelt N, vervierfacht sich die Arbeit.

Wachstumsvergleichstabelle:

| N | O(1) | O(N) | O(N²) |

|---|------|------|-------|

| 10 | 1 | 10 | 100 |

| 100 | 1 | 100 | 10,000 |

| 1,000 | 1 | 1,000 | 1,000,000 |

Bei N=10 sieht der Unterschied gering aus. Bei N=1.000 wird der Unterschied riesig.

Vergleich zwischen O(N) und O(N²)

Verwenden Sie die obenstehende Wachstumsvergleichstabelle.

Bei N=1.000: O(N) benötigt 1.000 Operationen. O(N²) benötigt 1.000.000 Operationen.

Bei N=1.000 benötigt O(N²) wie viel mehr Operationen im Vergleich zu O(N)? Zeigen Sie Ihre Arbeit.

Wie die Struktur des Codes die Komplexität offenbart

Wie man Big O aus dem Code identifiziert

Big O versteckt sich in der Form Ihres Codes. Vier Muster decken die meisten Fälle ab:

Schleife über N Elemente: O(N)

# O(N): eine Durchgang durch die Liste
for item in list_of_n_items:
    process(item)

Doppelte Schleifen, jede über N Elemente: O(N²)

# O(N²): jedes Element wird mit jedem anderen Element verglichen
for item_a in list_of_n_items:
    for item_b in list_of_n_items:
        compare(item_a, item_b)

Konstantzeit-Suche: O(1)

Zugriff auf ein Array-Index, Suche in einem Hash-Tabelle — unabhängig von der Größe ein Schritt.

Teilungs-und-konquere-Strategie (teile das Problem jedes Schritts): O(log N)

Binäre Suche: Jeder Check halbiert die verbleibenden Elemente.

---

Versteckte O(N²): eine Liste innerhalb einer Schleife

# Das sieht wie O(N) aus, aber es ist tatsächlich O(N²)
visited = []
for item in list_of_n_items:
    if item not in visited:   # scannt alle Elemente von visited: O(N)
        visited.append(item)  # die gesamte Schleife: O(N²)

Die Zeile if item not in visited scannt jedes Element von visited in jeder Iteration. Ein Skannen einer Liste kostet O(N). Eine Schleife, die N Male läuft, wobei jeder Schleifendurchgang O(N) Arbeit erfordert: O(N) × O(N) = O(N²).

Dieses Muster tritt in über 1.000 Open-Source-Projekten auf. Der Fix benötigt einen Zeichen: Ersetzen Sie visited = [] durch visited = set(). Die Prüfung der Mitgliedschaft in einem Satz kostet O(1), nicht O(N). Ein Änderungsantrag. Die gleichen Ergebnisse. 1.000× schneller bei N=1.000

Klasse und behebe diesen Code

Lesen Sie diesen Code:

result = []
for name in student_names:
    if name not in result:
        result.append(name)
Was ist die Big O-Komplexität dieses Codes? Erkläre, warum die Zeile `if name not in result` ihn teuer macht. Ändere dann den Code, um ihn in O(N) umzuwandeln.

Theorie trifft Praxis

Big O in der Wildnis

Big O ist nicht nur Theorie. Sie trennt Programme, die in Sekunden abgeschlossen werden von Programmen, die bei der gleichen Aufgabe 17 Minuten dauern.

Echter Fall: Abhängigkeitskreis-Detektion in einem Build-System.

Wenn Sie Software installieren, löst Ihre Computer ein Graph der Abhängigkeiten: Paket A benötigt B, B benötigt C und so weiter. Ein Build-System prüft diesen Graph auf Kreise.

Ein O(N²)-Algorithmus zur Kreis-Detektion funktioniert bei N=100 Paketen gut. Bei N=50.000 Paketen (ein echter Projekt): es dauert 17 Minuten. Der O(N)-Fix: 10 Sekunden.

Dieser genaue Fehler existiert in GHC (Haskell-Compiler), pip (Python-Pakete-Manager), Maven (Java-Build-System), Cargo (Rust-Pakete-Manager) und 1.000+ anderen Projekten.

Nicht, weil ihre Autoren sorglos waren. visited = [] wurde geschrieben, als N klein war. Der Code verfestigte sich. N wuchs. Niemand bemerkte, bis der Build 30 Minuten dauerte.

Big O ist die Sprache, die Ihnen erlaubt, das zu benennen, was passiert ist - und es zu beheben.

---

Möchten Sie tiefer gehen? Unser unverzerrter Kurs enthält einen ganzen Kapitel über Big O, MOAD-0001 (ein echter O(N²)-Defekt, der in 1.000+ Open-Source-Projekten gefunden wurde), und warum das Benennen eines Musters Ihnen das Finden überall ermöglicht. Siehe [Das fehlende Kapitel: Algoritmische Komplexität](/de/un/unhamming_algorithmic_complexity).

Vorhersage der Build-Zeiten

Ein Build-System verwendet O(N²)-Kreis-Detektion.

Messbare Build-Zeiten:

- N=100 Pakete: 0,01 Sekunden

- N=1.000 Pakete: 1 Sekunde

Für O(N²): Die Zeit skaliert als (N_new / N_alt)².

Für O(N): Die Zeit skaliert als (N_new / N_alt).

Mit diesen Formeln und gemessenen Daten: (A) bei N=10.000, wie lange dauert die O(N²)-Version? (B) nach einem O(N)-Fix, unter Verwendung von N=1.000 als Basis, wie lange dauert die O(N)-Version bei N=10.000? Zeigen Sie Ihr Arbeitsgang für beide.