Big O, wie kann Sie berechnen/approximieren?
Meisten Menschen mit einem Grad in CS wird sicherlich wissen, was Big O steht für.
Es hilft uns, zu Messen, wie (in)effizient ein Algorithmus wirklich ist und wenn Sie wissen, in in welche Kategorie das problem, das Sie versuchen zu lösen, liegt in können Sie herausfinden, ob es noch möglich ist, squeeze-out, die wenig extra-Leistung.1
Aber ich bin neugierig, wie Sie berechnen oder annähernd der Komplexität der algorithmen?
1 aber wie Sie sagen, übertreiben Sie es nicht, vorzeitige Optimierung ist die Wurzel allen übels und Optimierung ohne begründeten Anlass sollte verdienen diesen Namen als gut.
Vielleicht haben Sie nicht wirklich brauchen, um verbessern Sie Ihr Algorithmus die Komplexität, aber Sie sollten zumindest in der Lage sein zu berechnen, um zu entscheiden,...
Ich fand das eine sehr klare Erklärung von Big O Big-Omega und Big-Theta: xoax.net/comp/sci/algorithms/Lesson6.php
-1: Seufzen, ein weiterer Missbrauch der BigOh. BigOh ist nur ein asymptotische Obere Schranke und kann für alles verwendet werden und ist nicht nur CS verbunden. Reden BigOh, als wenn es ein eindeutige ist sinnlos (Ein linearzeit-Algorithmus auch O(n^2), O(n^3) usw.). Sagen, es hilft uns, Messen der Wirkungsgrad ist irreführend zu. Auch, was ist mit dem link, um die Komplexität von Klassen? Wenn alles, was Sie interessiert, ist Techniken zum berechnen der Laufzeiten von algorithmen, wie ist das relevant?
Big-O nicht Messen Effizienz; es misst, wie gut ein Algorithmus skaliert mit der Größe (es könnte für andere Dinge als die Größe auch, aber das ist, was wir wahrscheinlich hier interessiert) - und das nur asymptotisch, also, wenn Sie Pech ein Algorithmus mit einem "kleineren" groß-O kann langsamer sein (wenn die Big-O gilt für Zyklen) als eine andere, bis Sie in extrem großer Zahl.
Die Wahl eines Algorithmus auf der Grundlage seiner Big-O Komplexität ist in der Regel ein wesentlicher Bestandteil der Programm-Entwurf. Es ist definitiv nicht ein Fall von "premature optimization", die in jedem Fall ist eine viel missbrauchte selektiven Zitat.
Ich fand das eine sehr klare Erklärung von Big O Big-Omega und Big-Theta: xoax.net/comp/sci/algorithms/Lesson6.php
-1: Seufzen, ein weiterer Missbrauch der BigOh. BigOh ist nur ein asymptotische Obere Schranke und kann für alles verwendet werden und ist nicht nur CS verbunden. Reden BigOh, als wenn es ein eindeutige ist sinnlos (Ein linearzeit-Algorithmus auch O(n^2), O(n^3) usw.). Sagen, es hilft uns, Messen der Wirkungsgrad ist irreführend zu. Auch, was ist mit dem link, um die Komplexität von Klassen? Wenn alles, was Sie interessiert, ist Techniken zum berechnen der Laufzeiten von algorithmen, wie ist das relevant?
Big-O nicht Messen Effizienz; es misst, wie gut ein Algorithmus skaliert mit der Größe (es könnte für andere Dinge als die Größe auch, aber das ist, was wir wahrscheinlich hier interessiert) - und das nur asymptotisch, also, wenn Sie Pech ein Algorithmus mit einem "kleineren" groß-O kann langsamer sein (wenn die Big-O gilt für Zyklen) als eine andere, bis Sie in extrem großer Zahl.
Die Wahl eines Algorithmus auf der Grundlage seiner Big-O Komplexität ist in der Regel ein wesentlicher Bestandteil der Programm-Entwurf. Es ist definitiv nicht ein Fall von "premature optimization", die in jedem Fall ist eine viel missbrauchte selektiven Zitat.
InformationsquelleAutor sven | 2008-08-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich werde mein bestes tun, um es hier erklären auf einfache Begriffe, aber seien Sie gewarnt, dass dieses Thema nimmt meine Schüler ein paar Monate, bis endlich begreifen. Weitere Informationen finden Sie auf den in Kapitel 2 von der Datenstrukturen und Algorithmen in Java Buch.
Gibt es keine mechanische Verfahren, die verwendet werden können, um die BigOh.
Als ein "Kochbuch", um die BigOh von einem Stück code, müssen Sie zunächst erkennen, dass Sie erstellen eine mathematische Formel zu zählen, wie viele Schritte der Berechnungen, die ausgeführt werden, gegeben eine Eingabe mit einer gewissen Größe.
Zweck ist einfach: zu vergleichen algorithmen aus theoretischer Sicht, ohne die Notwendigkeit, um den code auszuführen. Lesser die Anzahl der Schritte, desto schneller ist der Algorithmus.
Zum Beispiel, sagen wir, Sie haben dieses Stück code:
Diese Funktion liefert die Summe aller Elemente des Arrays, und wir möchten, erstellen Sie eine Formel zum zählen der computational Komplexität der Funktion:
So haben wir
f(N)
eine Funktion zum zählen der Anzahl der rechnerische Schritte. Der Eingang der Funktion wird die Größe der Struktur zu verarbeiten. Es bedeutet, dass diese Funktion aufgerufen wird, wie:Den parameter
N
nimmt diedata.length
Wert. Jetzt müssen wir die eigentliche definition der Funktionf()
. Dies erfolgt aus dem source-code, in dem jeder interessante Zeile ist von 1 bis 4 nummeriert.Gibt es viele Wege, um die Berechnung der BigOh. Von diesem Punkt gehen wir davon aus, dass jeder Satz, der nicht abhängig von der Größe der Eingabedaten braucht eine Konstante
C
Anzahl rechnerische Schritte.Werden wir die individuelle Anzahl der Schritte von der Funktion, und weder die lokale Variablendeklaration noch die return-Anweisung hängt von der Größe der
data
array.Das bedeutet, dass die Linien 1 und 4 C Anzahl der Schritte, die Funktion ist etwas wie dieses:
Den nächsten Teil ist, definieren Sie den Wert der
for
- Anweisung. Denken Sie daran, dass wir zählen die Anzahl der rechnerischen Schritte, was bedeutet, dass der Körper desfor
- Anweisung ausgeführtN
Zeiten. Das ist das gleiche wie das hinzufügenC
,N
mal:Es gibt keine mechanische Regel, zu zählen, wie viele Male die Körper der
for
ausgeführt wird, müssen Sie es zählen, indem Sie betrachten, was bedeutet der code tun. Um die Rechnungen zu vereinfachen, wir ignorieren einfach die Variablen-Initialisierung, Bedingung und Inkrement Teile derfor
- Anweisung.Wird die tatsächliche BigOh wir müssen die Asymptotische Analyse der Funktion. Das ist in etwa so geschehen:
C
.f()
Holen Sie sich die polynomium in seinerstandard form
.N
Ansätzeinfinity
.Unserer
f()
hat zwei Bedingungen:Nehmen alle
C
Konstanten und redundante Teile:Da der Letzte term ist die eine, die wächst, wenn
f()
gegen unendlich (glaube auf Grenzen) dies ist die BigOh argument, und diesum()
Funktion hat eine BigOh:Gibt es ein paar tricks zu lösen, einige tricky ones: verwenden Summen, Wann immer Sie können.
Als Beispiel, dieser code kann leicht gelöst werden, mit Summen:
Das erste, was Sie brauchen, zu Fragen ist die Reihenfolge der Ausführung der
foo()
. Während der üblichen istO(1)
Sie müssen Fragen Sie Ihre Professoren darüber.O(1)
bedeutet (fast, nahezu) konstantC
unabhängig von der GrößeN
.Den
for
Aussage auf den Satz Nummer eins ist heikel. Während der index endet auf2 * N
der Schrittweite erfolgt durch zwei. Das bedeutet, dass die erstenfor
wird nur ausgeführtN
Schritte, und wir müssen, teilen Sie die Anzahl von zwei.Den Satz Anzahl zwei ist noch schwieriger, da kommt es auf den Wert der
i
. Werfen Sie einen Blick: der index i nimmt die Werte: 0, 2, 4, 6, 8, ..., 2 * N, und die zweitefor
ausgeführt werden: N-mal die erste, N - 2 die zweite, N - 4, die Dritte... bis zur N /2 Bühne, auf der sich die zweitefor
wird nie ausgeführt.Formel, das bedeutet:
Wieder, wir zählen die Anzahl der Schritte. Und per definition, jede Summe sollte beginnen immer mit einer, und am Ende eine Nummer größer-oder-gleich als eine.
(Wir gehen davon aus, dass
foo()
istO(1)
und nimmtC
Schritte.)Wir haben hier ein problem: wenn
i
nimmt den WertN /2 + 1
nach oben, die innere Summe endet bei einer negativen Zahl! Das ist unmöglich und falsch. Wir müssen, teilen Sie die Summe in zwei, wobei der Dreh-und Angelpunkt der momenti
nimmtN /2 + 1
.Da der entscheidende moment
i > N /2
, die innerefor
wird nicht ausgeführt, und wir sind der Annahme einer Konstanten C Ausführung Komplexität auf seinen Körper.Nun die Summen vereinfacht werden können, mit einigen identity-Regeln:
w
)Anwendung einiger algebra:
Und die BigOh ist:
Es hängt davon ab. Es ist
O(n)
won
ist die Anzahl der Elemente, oderO(x*y)
wox
undy
sind die Dimensionen des Arrays. Big-oh "relativ zum input", also es hängt davon ab, was ist Ihr input.Tolle Antwort, aber ich bin wirklich stecken. Wie funktioniert die Summation(i von 1 bis N / 2)( N ) verwandelt sich in ( N ^ 2 / 2 ) ?
Als Allgemeine Regel gilt, sum(i aus 1-a) (b) ist a * b. Dies ist nur eine andere Art zu sagen: b+b+...(ein mal)+b = a * b (per definition für einige Definitionen von integer-Multiplikation).
Nicht so relevant, aber nur um Verwirrung zu vermeiden, gibt es einen winzigen Fehler in diesem Satz: "der index i nimmt die Werte: 0, 2, 4, 6, 8, ..., 2 * N". Index i geht tatsächlich bis zu 2 * N - 2 ist, wird die Schleife stoppen dann.
InformationsquelleAutor vz0
Big O gibt die Obere Schranke für die Zeitkomplexität eines Algorithmus. Es ist in der Regel in Verbindung mit der Verarbeitung von Datensätzen (Listen), aber es kann an anderer Stelle eingesetzt werden.
Ein paar Beispiele, wie es in C-code.
Sagen, wir haben ein array von n Elementen
Wenn wir wollten, um Zugriff auf das erste element des Arrays wäre dies O(1) da ist es egal, wie groß das array ist, es dauert immer die gleiche Konstante Zeit, um das erste Element.
Wenn wir wollten eine Nummer in der Liste:
Wäre dies O(n) da am meisten, die wir sehen müssten, um durch die gesamte Liste, finden Sie unsere Nummer. Die Big-O immer noch O(n), obwohl wir finden, könnten wir unsere Nummer der ersten zu versuchen, und führen durch die Schlaufe einmal, da die Big-O beschreibt die Obere Grenze für einen Algorithmus (omega ist für die untere Schranke und theta ist für eng-gebunden ist).
Wenn wir geschachtelte Schleifen:
Dies ist in O(n^2), da für jeden Durchlauf der äußeren Schleife ( O(n) ) haben wir zu gehen durch die gesamte Liste wieder, so dass die n multiplizieren, indem Sie uns mit n im Quadrat.
Dies ist kaum an der Oberfläche gekratzt, aber wenn Sie die Analyse komplexer algorithmen, die komplexe mathematische Beweise mit ins Spiel kommt. Hoffe, das macht Sie mit den Grundlagen zumindest wenn.
Nicht wirklich, jeder Aspekt, führen zu n-Quadrat mal als n^2
Sie werden nicht immer sehen der nested-loop -, als Funktionsaufrufe tun können, >
O(1)
sich selbst zu arbeiten. In der C-standard-APIs zum Beispielbsearch
ist von Natur ausO(log n)
,strlen
istO(n)
, undqsort
istO(n log n)
(technisch gesehen hat es keine Garantien, und quicksort hat selbst ein worst-case-Komplexität vonO(n²)
, aber vorausgesetzt, Ihrlibc
Autor ist kein idiot, seine durchschnittlichen Fall Komplexität istO(n log n)
und es verwendet eine pivot-Auswahl-Strategie, die die Verschiedenheit des Schlagens derO(n²)
Fall). Und beidebsearch
undqsort
können noch schlimmer sein, wenn der Komparator-Funktion ist pathologisch.InformationsquelleAutor DShook
Während zu wissen, wie um herauszufinden, die Big O Zeit für Ihr spezielles problem ist nützlich, zu wissen, einige Allgemeine Fälle können gehen einen langen Weg zu helfen, Sie Entscheidungen treffen, die in Ihrem Algorithmus.
Hier sind einige der häufigsten Fälle, gehoben von http://en.wikipedia.org/wiki/Big_O_notation#Orders_of_common_functions:
O(1) - der Bestimmung, ob eine Zahl gerade oder ungerade ist; die Verwendung eines konstant-Größe lookup-Tabelle oder eine hash-Tabelle
O(logn) - suchen eines Elements in ein sortiertes array mit binärer Suche
O(n) - suchen eines Elements in einer unsortierten Liste, das hinzufügen von zwei n-stelligen zahlen
O(n2) - Multiplizieren von zwei n-stelligen zahlen, die durch einen einfachen Algorithmus, um zwei n×n-Matrizen; bubble sort oder insertion sort
O(n3) - Multiplikation zweier n×n Matrizen durch einfache Algorithmus
O - (cn) - Finden die (exakte) Lösung des traveling salesman Problems mittels dynamischer Programmierung; bestimmen, ob zwei logische Aussagen sind äquivalent: brute-force -
O(n!) - Die Lösung des traveling salesman problem via brute-force-Suche
O(nn) - Oft verwendet, anstelle von O(n!) zur Ableitung einfacher Formeln für die asymptotische Komplexität
Warum nicht
x&1==1
zu prüfen, für die Ungereimtheit?Das wäre eine typische Art und Weise zu überprüfen (eigentlich nur testen
x & 1
wäre ausreichend, keine Notwendigkeit zu prüfen== 1
; in C,x&1==1
wird ausgewertet, wiex&(1==1)
Dank Rangfolge, es ist also eigentlich das gleiche wie Testsx&1
). Ich glaube, du bist verlesen der Antwort, obwohl; es ist ein semi-Kolon, nicht ein Komma. Es ist nicht zu sagen, Sie müssten eine lookup-Tabelle für gerade/ungerade-Test, es besagt sowohl gerade/ungerade-Test und Prüfung einer lookup-Tabelle sindO(1)
Operationen.Wort. Wahre Punkt.
InformationsquelleAutor Giovanni Galbo
Kleine Erinnerung: die
big O
- notation wird verwendet, um anzuzeigen asymptotische Komplexität (das heißt, wenn die Größe des Problems wächst bis unendlich), und es verbirgt eine Konstante.Dies bedeutet, dass zwischen ein Algorithmus in O(n) und O(n2), der Schnellste ist nicht immer der erste (obwohl es gibt immer einen Wert von n so, dass für Probleme der Größe >n, der erste Algorithmus ist der Schnellste).
Beachten Sie, dass die versteckten Konstanten sehr viel hängt von der Umsetzung!
Auch in einigen Fällen, die Laufzeit ist nicht eine deterministische Funktion der Größe n der Eingabe. Nehmen Sie das Sortieren mit quick-sort-Beispiel: die benötigte Zeit zum Sortieren eines Arrays von n Elementen ist nicht konstant, sondern hängt von der Start-Konfiguration des Arrays.
Gibt es verschiedene Zeit-Komplexität:
Durchschnittlichen Fall (in der Regel viel härter, um herauszufinden,...)
...
Eine gute Einführung ist Eine Einführung in die Analyse von Algorithmen von R. Sedgewick und P. Flajolet.
Wie Sie sagen,
premature optimisation is the root of all evil
, und (wenn möglich) profiling wirklich sollte immer verwendet werden, wenn die Optimierung von code. Es kann sogar helfen, Sie bestimmen die Komplexität der algorithmen.InformationsquelleAutor OysterD
Sehen die Antworten hier, ich denke, wir können feststellen, dass die meisten von uns tun, in der Tat annähernd die Reihenfolge der Algorithmus von suchen Sie an und verwenden Sie gesunden Menschenverstand, anstatt ihn zu berechnen, zum Beispiel, die master-Methode, wie wir waren, dachten an der Universität.
Mit dieser sagte ich muss hinzufügen, dass sogar der professor hat uns ermutigt, (später) tatsächlich denke über es, anstatt nur die Berechnung.
Ich würde auch gerne hinzufügen, wie es gemacht wird für rekursive Funktionen:
nehmen wir an, wir haben eine Funktion wie (scheme-code):
welche rekursiv berechnet die Fakultät der Zahl angegeben.
Der erste Schritt ist, zu versuchen und zu bestimmen, die performance-Charakteristik für die Körper der Funktion nur in diesem Fall, nichts besonderes getan wird, in der Körper, nur eine Multiplikation (oder die Rückgabe des Wertes 1).
Also die Leistung für den Körper ist: O(1) (Konstante).
Nächsten versuchen und zu bestimmen, das für die Anzahl der rekursiven Aufrufe. In diesem Fall haben wir n-1 rekursive Aufrufe.
Also die Leistung für die rekursiven Aufrufe ist: O - (n-1) (Ordnung n ist, wie wir wegwerfen, die unwesentlichen teilen).
Dann setzen sich die beiden zusammen und Sie haben dann die Leistung für die gesamte rekursive Funktion:
1 * (n-1) = O(n)
Peter, zu beantworten Ihre aufgeworfenen Fragen; die Methode, die ich hier beschreibe tatsächlich behandelt das sehr gut. Aber Bedenken Sie, dass dies ist immer noch ein Annäherung und nicht eine vollständige mathematisch korrekte Antwort. Die hier beschriebene Methode ist auch eine der Methoden, die wir waren, lehrte an der Universität, und wenn ich mich richtig erinnere, wurde für weit mehr fortschrittliche algorithmen, als die Fakultät, die ich in diesem Beispiel verwendet.
Natürlich ist es hängt alles davon ab, wie gut Sie schätzen können, die Laufzeit der Körper der Funktion und die Anzahl der rekursiven Aufrufe, aber das gilt nicht nur für die anderen Methoden.
+1 für die Rekursion... Auch das ist schön: "...auch der professor hat uns ermutigt, zu denken..." 🙂
Ja, das ist so gut. Ich Neige dazu, zu denken , wie diese, höher ist der Begriff im inneren O(..) , mehr zu der Arbeit die man / Maschine tut. Denken Sie, während Sie in Bezug auf etwas, das vielleicht eine Annäherung , aber so sind diese Schranken. Sie nur sagen, wie es tut die Arbeit, die getan werden erhöht, wenn die Anzahl der Eingänge erhöht werden.
InformationsquelleAutor sven
Wenn Sie Ihre Kosten ist ein Polynom, nur halten die höchsten um-Sicht, ohne Multiplikator. E. g.:
Funktioniert das nicht bei unendlichen Reihen, wohlgemerkt. Es gibt nicht das Rezept für den Allgemeinen Fall, obwohl es für einige häufige Fälle, die folgende Ungleichungen gelten:
InformationsquelleAutor Marcelo Cantos
Ich denke, über die es in Bezug auf die Informationen. Jedes problem besteht aus lernen, eine bestimmte Anzahl von bits.
Ihre grundlegende Werkzeug ist das Konzept der Entscheidungspunkte und deren Entropie. Die Entropie einer Entscheidung ist der Durchschnitt, wird es geben Sie. Zum Beispiel, wenn ein Programm enthält eine Entscheidung mit zwei Niederlassungen, die Entropie ist die Summe der Wahrscheinlichkeit jedes Zweigs mal die log2 der inversen Wahrscheinlichkeit, dass dieser Zweig. Das ist, wie viel Sie lernen durch die Ausführung der Entscheidung.
Beispielsweise eine
if
- Anweisung mit zwei Zweigen, die beide gleich wahrscheinlich sind, hat eine Entropie von 1 /2 * log(2/1) + 1/2 * log(2/1) = 1/2 * 1 + 1/2 * 1 = 1. Also seine Entropie 1 bit.Angenommen, Sie sind auf der Suche eine Tabelle von N Elementen, wie N=1024. Das ist ein 10-bit-problem, weil log(1024) = 10 bit. Also, wenn Sie können, suchen Sie es mit, WENN Aussagen, Ergebnisse gleich wahrscheinlich sind, sollte es nehmen 10 Entscheidungen.
Das ist, was Sie erhalten mit binären Suche.
Angenommen, Sie sind dabei lineare Suche. Sie schauen auf das erste element und Fragen, ob es die, die Sie wollen. Die Wahrscheinlichkeiten sind 1/1024, dass es ist, und 1023/1024, dass es nicht so ist. Die Entropie, die Entscheidung ist 1/1024*log(1024/1) + 1023/1024 * melden(1024/1023) = 1/1024 * 10 + 1023/1024 * über 0 = über 01 bit. Sie haben gelernt, sehr wenig! Die zweite Entscheidung ist auch nicht viel besser. Deshalb ist die lineare Suche ist so langsam. In der Tat, es ist exponentiell in der Anzahl der bits, die Sie brauchen, um zu lernen.
Nehme an, Sie tun Indizierung. Nehmen wir an, die Tabelle ist vorsortiert in einer Menge von Behältern, und verwenden Sie einige der alle bits in dem Schlüssel-index direkt auf den Tabelleneintrag. Wenn es 1024 bins, die Entropie ist 1/1024 * log(1024) + 1/1024 * log(1024) + ... für alle 1024 möglichen Ergebnisse. Dies ist 1/1024 * 10 mal 1024 Ergebnisse, oder 10 bits Entropie, die eine Indizierung Betrieb. Deshalb ist die Indizierung Suche schnell.
Denken Sie jetzt an das Sortieren. Sie haben N Elemente, und Sie haben eine Liste. Für jedes Element, die Sie haben zu suchen, wo das Element geht in die Liste, und fügen Sie es der Liste. So Sortieren dauert etwa N mal die Anzahl der Schritte von der zugrunde liegenden suchen.
So sortiert, basierend auf binären Entscheidungen, die etwa gleich wahrscheinlich, Ergebnisse alle etwa O(N log N) Schritte. Ein O(N) sort-Algorithmus ist möglich, wenn es sich auf die Indizierung der Suche.
Ich habe festgestellt, dass fast alle algorithmischen performance-Probleme können angeschaut werden auf diese Weise.
Für was es Wert ist, ich ein Buch geschrieben abdeckt, und andere Themen. Es ist längst vergriffen, Kopien gehen für einen angemessenen Preis. Ich habe versucht, GoogleBooks, um es zu packen, aber im moment ist es ein wenig schwer, herauszufinden, wer hat das copyright.
InformationsquelleAutor Mike Dunlavey
Können von vorne beginnen.
Zunächst grundsätzlich akzeptieren, dass bestimmte einfache Operationen auf den Daten getan werden kann, in
O(1)
Zeit, das heißt, in der Zeit, die unabhängig von der Größe der Eingabe. Diese primitiven Operationen in C bestehen auslowing mit der -> operator).
Ist die Begründung für dieses Prinzip erfordert eine detaillierte Studie über die Maschinen-Anweisungen (primitives) Schritte eines typischen computer. Jede der beschriebenen Operationen kann man mit einem kleinen Anzahl der Maschinenbefehle; oft nur eine oder zwei Anweisungen erforderlich sind.
Als Folge, mehrere Arten von Anweisungen in C ausgeführt werden kann
O(1)
Zeit, das heißt, in einigen konstanter Zeit unabhängig von der Eingabe. Diese einfachen zählenAusdruck nicht enthält einen Aufruf der Funktion.
In C, viele for-Schleifen werden gebildet, indem beim initialisieren des index-variable auf einen Wert und
Inkrementieren Sie die variable um 1 jedes mal um die Schleife. Die for-Schleife endet, wenn
der index erreicht den Grenzwert. Zum Beispiel, die for-Schleife
verwendet index-variable, die ich. Es erhöht i um 1 jedes mal um die Schleife, und die Iterationen
stoppen Sie, wenn ich erreicht n − 1.
Jedoch für den moment, konzentrieren sich auf die einfache form der for-Schleife, wo die Unterschied zwischen dem letzten und ursprünglichen Werte, geteilt durch den Betrag, um den der index-variable um eins erhöht, zeigt uns, wie viele Male haben wir gehen, um die Schleife. Diese Zählung ist präzise, es sei denn, es gibt Möglichkeiten zum verlassen der Schleife über eine jump-Anweisung; es ist eine Obere Schranke für die Anzahl von Iterationen in jedem Fall.
Beispielsweise die for-Schleife iteriert
((n − 1) − 0)/1 = n − 1 times
,da 0 der Anfangswert von i, n − 1 ist der höchste Wert wird erreicht durch i (D. H., wenn ich
erreicht n−1, wird die Schleife abgebrochen und es werden keine iteration erfolgt mit i = n−1), und 1 Hinzugefügt
bis ich dann bei jeder iteration der Schleife.
Im einfachsten Fall, wo die verbrachte Zeit in der Schleife ist die gleiche für jeden
iteration, multiplizieren wir die big-oh Obergrenze für den Körper durch die Anzahl der
mal um die Schleife. Streng genommen, müssen wir dann add O(1) Zeit, Sie zu initialisieren
der loop-index und O(1) Zeit für den ersten Vergleich in der Schleife mit dem index
limit, weil wir den test noch ein mal, als wir gehen um die Schleife. Jedoch, es sei denn,
es ist möglich, führen Sie die Schleife null mal, die Zeit zur Initialisierung der Schleife und testen
die Grenze once ist ein low-order-Begriff, der gelöscht werden können, durch die Summierung der Regel.
Betrachten wir nun dieses Beispiel:
Wissen wir, dass Linie (1) nimmt
O(1)
Zeit. Klar, wir gehen um die Schleife n-mal, alswir können bestimmen, indem man die untere Grenze von der oberen Grenze gefunden auf line
(1) und dann hinzufügen 1. Da der Körper -, Linien - (2), O(1) Zeit, können wir vernachlässigen die
Zeit Inkrementieren j und der Zeit zu vergleichen, j mit n, die beide ebenfalls O(1).
Also, die Laufzeit der Zeilen (1) und (2) ist die Produkt von n und O(1), die
O(n)
.Ebenso können wir gebunden die Laufzeit der äußeren Schleife, bestehend aus Linien
(2) bis (4), die
Wir haben bereits festgestellt, dass die Schleife der Zeilen (3) und (4) in O(n) Zeit.
So können wir vernachlässigen der O(1) Zeit-Inkrement i und um zu testen, ob die i < n in
jede iteration, die Feststellung, dass jede iteration der äußeren Schleife dauert O(n) Zeit.
Die Initialisierung i = 0 der äußeren Schleife und der (n + 1)st test der Bedingung
i < n ebenso nehmen O(1) Zeit und kann vernachlässigt werden. Schließlich beobachten wir, dass wir gehen
um die äußere Schleife n-mal, wobei O(n) Zeit für jede iteration, was eine Gesamtzahl
O(n^2)
Laufzeit.Beispiel aus der Praxis.
InformationsquelleAutor ajknzhol
Wenn Sie wollen, zu schätzen, die Reihenfolge der code-empirisch eher als durch die Analyse des Codes konnte-stick in einer Reihe von zunehmenden Werten von n und time code. Zeichnen Sie Ihre Zeiten auf einer log-Skala. Wenn der code O(x^n), die Werte fallen sollten auf einer Linie der Steigung n.
Diese hat mehrere Vorteile gegenüber nur den Quellcode zu untersuchen. Für eine Sache, können Sie sehen, ob Sie in den Bereich, wo die Laufzeit nähert sich seinem asymptotische Ordnung. Auch, Sie können feststellen, dass einige der code, den Sie dachte, war die Ordnung O(x) ist O(x^2), zum Beispiel, weil die Zeit, in der Bibliothek anrufen.
Hi, nette Antwort. Ich Frage mich, wenn Sie Kenntnis über Bibliothek oder Methodik (ich arbeite mit python/R zum Beispiel) zu verallgemeinern empirischen Methode, was bedeutet, wie das Zusammenfügen von Komplexität auf verschiedenen Funktionen zu Erhöhung der Größe dataset, und finden Sie heraus, was relevant ist. Dank
InformationsquelleAutor John D. Cook
Im Grunde war die Sache, dass Pflanzen bis zu 90% der Zeit ist nur die Analyse von Schleifen. Sie haben Einzel -, Doppel -, dreifach verschachtelten Schleifen? Sie haben O(n), O(n^2), O(n^3) Laufzeit.
Sehr selten (es sei denn, Sie schreiben eine Plattform mit einer umfangreichen Basis-Bibliothek (wie zum Beispiel die .NET BCL, oder C++'s STL) Sie begegnen werden, nichts ist schwieriger, als ein Blick auf Ihre Schleifen (for-Anweisungen, while -, goto, etc...)
InformationsquelleAutor Adam
Brechen den Algorithmus in Stücke, die Sie wissen, die big-O-notation, und kombinieren durch die große O-Operatoren. Das ist die einzige Möglichkeit, die ich kenne.
Weitere Informationen, überprüfen Sie die Wikipedia-Seite auf das Thema.
InformationsquelleAutor Lasse Vågsæther Karlsen
Big O-notation ist nützlich, weil es ist einfach, mit zu arbeiten und blendet unnötige Komplikationen und details (für eine definition von unnötig). Eine schöne Art der arbeiten, die Komplexität der Teile und herrsche-algorithmen ist die Baum-Methode. Lassen Sie uns sagen, Sie haben eine version von quicksort mit median-Verfahren, so dass Sie split das array in perfekt ausgewogenen subarrays jeder Zeit.
Jetzt bauen Sie einen Baum entsprechend alle arrays mit dem Sie arbeiten. An der Wurzel haben Sie das original-array, die Wurzel hat zwei Kinder, die die subarrays. Wiederholen Sie dies, bis Sie haben Einzel-element-arrays auf der Unterseite.
Da finden wir den median in O(n) Zeit-und split das array in zwei Teile, die in O(n) Zeit, die Arbeit an jedem Knoten ist O(k) wobei k die Größe des Arrays. Jede Ebene des Baums enthält (bei den meisten) der gesamten array also die Arbeit pro Stufe O(n) (die Größe des subarrays summieren sich zu n, und da wir O(k) pro Stufe können wir hinzufügen). Es gibt nur log(n) Ebenen in der Struktur, da jedes mal, wenn wir eine Halbierung der Eingang.
Deshalb können wir die Obere Grenze der Menge der Arbeit von O(n*log(n)).
Aber Big O verbirgt einige details, die wir manchmal nicht ignorieren kann. Betrachten Berechnung der Fibonacci-Sequenz mit
und lässt annehmen, dass a und b sind BigIntegers in Java oder etwas, das verarbeiten kann beliebig große zahlen. Die meisten Menschen würden sagen, dies ist eine O(n) Algorithmus, der ohne mit der Wimper zu zucken. Die Argumentation ist, dass Sie n Iterationen der for-Schleife O(1) Arbeit in der Seite der Schleife.
Aber Fibonacci-zahlen sind groß, die n-te Fibonacci-Zahl ist exponentiell in n, so dass nur die Speicherung wird die Ordnung von n bytes. Neben der Durchführung mit großen ganzen zahlen dauert O(n) Aufwand. So der Gesamtbetrag der Arbeit, die in dieses Verfahren ist
1 + 2 + 3 + ... + n = n(n-1)/2 = O(n^2)
Damit dieser Algorithmus läuft in quadradic Zeit!
Man sollte sich keine Gedanken darüber, wie die Nummern gespeichert sind, ändert es nichts, dass der Algorithmus wächst bei einer Obergrenze von O(n).
InformationsquelleAutor
Vertrautheit mit den algorithmen/Datenstrukturen, die ich verwenden und/oder quick-Blick-Analyse-iteration, nesting. Die Schwierigkeit ist, wenn Sie anrufen, eine library-Funktion, die möglicherweise mehrfach - oft können Sie unsicher sein, ob Sie die Funktion aufrufen, unnötig an Zeiten oder welche Implementierung Sie verwenden. Vielleicht Bibliotheksfunktionen sollten eine Komplexität/Effizienz Messen, ob das Große O oder eine andere Metrik, die in der Dokumentation oder sogar IntelliSense.
InformationsquelleAutor Matt Mitchell
Weniger nützlich im Allgemeinen, denke ich, aber der Vollständigkeit halber gibt es auch eine Große Omega Ω definiert, die eine untere Schranke für einen Algorithmus der Komplexität, und ein Große Theta Θ definiert, die sowohl eine Obere und untere Schranke.
InformationsquelleAutor Martin
Als "wie berechnen Sie die" Big O, das ist ein Teil von Komplexitätstheorie. Für einige (viele) in besonderen Fällen können Sie in der Lage zu kommen mit einigen einfachen Heuristiken (wie Multiplikation Schleife zählt für verschachtelte Schleifen), esp. wenn alle Sie wollen, ist jeder upper bound-Schätzung, und es Sie nicht stört, wenn er zu pessimistisch - ich glaube, das ist wahrscheinlich das, was Ihre Frage ist.
Wenn Sie wirklich wollen, um Ihre Frage zu beantworten, die für jeden Algorithmus die beste Sie tun können, ist die Anwendung der Theorie. Neben der simpel "worst-case" - Analyse, die ich gefunden habe Amortisierten Analyse sehr nützlich in der Praxis.
InformationsquelleAutor Suma
Für den 1. Fall wird die innere Schleife ausgeführt wird
n-i
Zeiten, so dass die Gesamtzahl der Hinrichtungen ist die Summe füri
gehen von0
zun-1
(weil niedriger als, nicht niedriger als oder gleich wie) dern-i
. Sie bekommen schließlichn*(n + 1) /2
, soO(n²/2) = O(n²)
.Für die 2. Schleife
i
ist zwischen0
undn
für die äußere Schleife; dann die innere Schleife wird ausgeführt, wennj
ist strikt größer alsn
, die ist dann unmöglich.InformationsquelleAutor Emmanuel
Neben der Verwendung der master Methode (oder eine seiner Spezialisierungen), ich Teste meine algorithmen experimentell. Dies kann nicht beweisen, dass eine bestimmte Komplexität-Klasse ist erreicht, es kann aber die Gewissheit, dass die mathematische Analyse geeignet ist. Zu helfen, mit dieser Gewissheit, ich benutze die code-coverage-tools in Verbindung mit meinen versuchen, um sicherzustellen, dass ich die Ausübung aller Fälle.
Als ein sehr einfaches Beispiel, sagen, Sie wollten eine überprüfung auf die Geschwindigkeit des .NET framework ist die Liste Sortieren. Könnten Sie etwas schreiben wie das folgende, dann analysieren Sie die Ergebnisse in Excel, um sicherzustellen, dass Sie nicht mehr als eine n*log(n) - Kurve.
In diesem Beispiel habe ich Messen die Zahl der Vergleiche, aber es ist auch ratsam zu prüfen, den tatsächlichen Zeitaufwand für die einzelnen sample-Größe. Aber dann müssen Sie noch vorsichtiger sein, dass Sie nur die Messung der Algorithmus und nicht einschließlich Artefakte aus dem test-Infrastruktur.
InformationsquelleAutor Eric
Vergessen Sie nicht auch Platz Komplexitäten, die können auch ein Grund zur Sorge, wenn man begrenzten Speicher-Ressourcen. So zum Beispiel, können Sie hören, wie jemand, die eine Konstante Raum-Algorithmus, die im Grunde ist eine Art zu sagen, dass die Menge der Raum genommen, indem der Algorithmus hängt nicht von irgendwelchen Faktoren innerhalb des Codes.
Manchmal die Komplexität kommt, wie oft etwas aufgerufen und wie oft wird eine Schleife ausgeführt, wie oft wird der Speicher zugewiesen, und so weiter ist ein weiterer Teil um diese Frage zu beantworten.
Schließlich big O kann verwendet werden, für die im schlimmsten Fall, im besten Fall, und Abschreibungen auf Fälle, in denen im Allgemeinen es ist das Schlimmste, das verwendet wird zum beschreiben, wie schlecht ein Algorithmus sein kann.
InformationsquelleAutor JB King
Was oft übersehen wird ist die erwartet Verhalten der algorithmen. Es nicht ändern, dass die Big-O Ihres Algorithmus, aber es nicht beziehen sich auf die Aussage "vorzeitige Optimierung. . .."
Erwartete Verhalten des Algorithmus ist -- sehr verdummt-wie schnell können Sie erwarten, dass Ihre algorithmen arbeiten auf Daten, die Sie wahrscheinlich zu sehen.
Zum Beispiel, wenn Sie auf der Suche nach einem Wert in einer Liste, es ist O(n), aber wenn Sie wissen, dass die meisten Listen, die Sie sehen, haben Ihren Wert vorne, typisches Verhalten des Algorithmus schneller ist.
Wirklich Nagel es sich, Sie müssen in der Lage sein zu beschreiben, in dem die Wahrscheinlichkeitsverteilung von Ihrem "input-Raum" (wenn Sie brauchen, um Sortieren eine Liste, wie oft wird diese Liste schon sortiert ist? wie oft ist es komplett Umgekehrt? wie oft ist es meist sortiert?) Es ist nicht immer machbar, dass Sie wissen, dass, aber manchmal tun Sie.
InformationsquelleAutor Baltimark
große Frage!
Disclaimer: diese Antwort enthält falschen Aussagen siehe die Kommentare unten.
Wenn Sie mit dem Großen O, Sie sprechen über die Worst-case - (mehr darüber, was das bedeutet, wird später). Darüber hinaus ist capital theta für den durchschnittlichen Fall und ein großes omega für den besten Fall.
Check out this site, für eine schöne formale definition von Big O: https://xlinux.nist.gov/dads/HTML/bigOnotation.html
Ok, so jetzt, was verstehen wir unter "best-case" und "worst-case" - Komplexität?
Dies ist wahrscheinlich am deutlichsten illustriert durch Beispiele. Zum Beispiel, wenn wir über lineare Suche einer Zahl in einem sortierten array dann die schlimmsten Fall ist, wenn wir uns entscheiden, Suche nach dem letzten element des Arrays als dies dauern würde, so viele Schritte, wie es Elemente im array. Die besten Fall wäre, wenn wir suchen für die erste element, denn wir würden nach dem ersten check.
Dem Punkt, der alle diese Adjektiv-case-Komplexität ist, dass wir auf der Suche nach einem Weg, um Diagramm die Zeit, die eine hypothetische Programm läuft bis zur Fertigstellung in Hinblick auf die Größe der betreffenden Variablen. Doch für viele algorithmen kann man argumentieren, dass es nicht ein einziges mal für eine bestimmte Größe der Eingabe. Beachten Sie, dass dies im Widerspruch mit der grundsätzlichen Anforderung einer Funktion, einem Eingang sollte nicht mehr als einen Ausgang. Also wir kommen mit mehrere Funktionen beschreiben einen Algorithmus der Komplexität. Nun, obwohl die Suche ein array der Größe n nehmen unterschiedliche Mengen an Zeit, je nachdem, was Sie suchen, in das array und je proportional zu n, erstellen wir eine informative Beschreibung des Algorithmus mit best-case, average-case und worst-case-Klassen.
Sorry das ist so schlecht geschrieben und es fehlen viele technische Informationen. Aber ich hoffe, es werde Zeit, Komplexität Klassen einfacher zu denken. Sobald Sie sich bequem mit dieser wird es eine einfache Sache zu analysieren, die durch Ihr Programm und suchen nach Dingen wie for-Schleifen, die davon abhängen, array-Größen und Argumentation basierend auf Ihren Daten-Strukturen, welche Art von input ergeben würde, in trivialen Fällen und welcher Eingang wäre die Folge, im schlimmsten Fälle.
Es ist ein verbreiteter Irrtum, dass big-O bezieht sich auf die worst-case. Wie O-und Ω beziehen sich auf worst und best case?
Dies ist irreführend. Big-O heißt Obere Schranke für eine Funktion f(n). Omega heißt untere Schranke für die Funktion f(n). Es ist überhaupt nicht im Zusammenhang mit best-case-oder worst-case.
Sie können Big-O als Obergrenze für entweder den besten oder den schlechtesten Fall, aber andere als, dass, ja keine Beziehung.
InformationsquelleAutor Samy Bencherif
Ich weiß nicht, wie Sie programmgesteuert dieses Problem lösen, aber das erste, was Menschen tun, ist, dass wir eine Probe der Algorithmus für bestimmte Muster in der Anzahl der Operationen, sagen 4n^2 + 2n + 1 haben wir 2 Regeln:
Wenn wir vereinfachen f(x), wobei f(x) ist die Formel für die Anzahl der Operationen, (4n^2 + 2n + 1 wie oben erklärt), so erhalten wir die big-O-Wert [O(n^2) in diesem Fall]. Aber dies hätte zur Rechenschaft für die Lagrange-interpolation im Programm, die vielleicht schwer zu implementieren. Und was ist, wenn der echte big-O-Wert von O(2^n), und wir haben vielleicht so etwas wie O(x^n), so dass dieser Algorithmus würde wahrscheinlich nicht programmierbar. Aber wenn jemand beweist mich falsch, gib mir den code . . . .
InformationsquelleAutor Gavriel Feria
Für code A, die äußere Schleife wird ausgeführt für
n+1
mal, die '1' heißt das Verfahren, das prüft, ob ich immer noch die Anforderungen erfüllt. Und die innere Schleife läuftn
maln-2
mal.... So0+2+..+(n-2)+n= (0+n)(n+1)/2= O(n²)
.Für code B, obwohl die innere Schleife würde nicht in Schritt und führen Sie die foo(), die innere Schleife wird ausgeführt für n-Zeiten hängen von äußeren Schleife Ausführungszeit ist O(n)
InformationsquelleAutor laynece
Ich möchte erklären, die Big-O in einem etwas anderen Aspekt.
Big-O ist nur zum Vergleich der Komplexität der Programme, das heißt, wie schnell werden Sie wachsen, wenn die Eingänge werden immer mehr und nicht die genaue Zeit verbringen zu tun.
IMHO in der big-O-Formeln, die Sie besser nicht zu verwenden komplexere Gleichungen (vielleicht stecken Sie nur diejenigen, die in der folgenden Grafik.) Allerdings könnten Sie noch verwenden andere genauere Formel (wie 3^n, n^3, ...), aber mehr als das kann manchmal irreführend! Also besser halten Sie es so einfach wie möglich.
Möchte ich noch einmal betonen, dass wir das hier nicht wollen, um eine exakte Formel für unseren Algorithmus. Wir wollen nur zeigen, wie es wächst, wenn die Eingänge wachsen und vergleichen Sie mit den anderen algorithmen in diesem Sinn. Sonst würden Sie besser verwenden verschiedene Methoden wie bench-marking.
InformationsquelleAutor HmT