Kann jemand die amortisierte Komplexität in Laienbegriffen erklären? Es fiel mir schwer, online eine genaue Definition zu finden, und ich weiß nicht, wie sie sich vollständig auf die Analyse von Algorithmen bezieht. Alles Nützliche, auch wenn es extern referenziert wird, wäre sehr dankbar.
algorithm
amortized-analysis
Bob John
quelle
quelle
Antworten:
Die Idee ist, die Gesamtkosten der gesamten Sequenz zu garantieren und gleichzeitig zu ermöglichen, dass einzelne Vorgänge viel teurer sind als die fortgeführten Anschaffungskosten.
Beispiel:
Das Verhalten von C ++
std::vector<>
. Wennpush_back()
die Vektorgröße über ihren vorab zugewiesenen Wert erhöht wird, wird die zugewiesene Länge verdoppelt.Die Ausführung eines einzelnen
push_back()
kann daher einigeO(N)
Zeit in Anspruch nehmen (da der Inhalt des Arrays in die neue Speicherzuordnung kopiert wird).Da jedoch die Größe der Zuordnung verdoppelt wurde, dauert die Ausführung der nächsten
N-1
Aufrufepush_back()
jeweils einigeO(1)
Zeit. Die Gesamtzahl derN
Operationen wird also nochO(N)
Zeit in Anspruch nehmen . Dadurch ergeben sichpush_back()
fortgeführte AnschaffungskostenO(1)
pro Operation.Sofern nicht anders angegeben, ist die amortisierte Komplexität eine asymptotische Worst-Case-Garantie für jede Abfolge von Operationen. Das heisst:
Genau wie bei der nicht amortisierten Komplexität ignoriert die für die amortisierte Komplexität verwendete Big-O-Notation sowohl den festen anfänglichen Overhead als auch konstante Leistungsfaktoren. Für die Bewertung der amortisierten Big-O-Leistung können Sie daher im Allgemeinen davon ausgehen, dass jede Folge von amortisierten Vorgängen "lang genug" ist, um einen festen Startaufwand zu amortisieren. Insbesondere für das
std::vector<>
Beispiel müssen Sie sich deshalb keine Gedanken darüber machen, ob Sie tatsächlich aufN
zusätzliche Operationen stoßen : Die asymptotische Natur der Analyse setzt dies bereits voraus.Abgesehen von der willkürlichen Länge werden bei der amortisierten Analyse keine Annahmen über die Abfolge von Vorgängen getroffen, deren Kosten Sie messen. Sie ist eine Worst-Case-Garantie für eine mögliche Abfolge von Vorgängen. Unabhängig davon, wie schlecht die Vorgänge ausgewählt werden (z. B. von einem böswilligen Gegner!), Muss eine amortisierte Analyse sicherstellen, dass eine ausreichend lange Abfolge von Vorgängen nicht durchgehend mehr kostet als die Summe ihrer amortisierten Kosten. Aus diesem Grund sind "Wahrscheinlichkeit" und "Durchschnittsfall" (sofern nicht ausdrücklich als Qualifikationsmerkmal angegeben) für die amortisierte Analyse nicht relevant - ebenso wenig wie für eine gewöhnliche Big-O-Analyse im schlimmsten Fall!
quelle
(von Cormen et al., "Introduction to Algorithms")
Das könnte etwas verwirrend sein, da es sowohl besagt, dass die Zeit gemittelt wird, als auch, dass es sich nicht um eine Durchschnittsfallanalyse handelt. Lassen Sie mich versuchen, dies mit einer finanziellen Analogie zu erklären (in der Tat ist "amortisiert" ein Wort, das am häufigsten mit Bank- und Rechnungswesen in Verbindung gebracht wird.)
Angenommen, Sie betreiben eine Lotterie. (Sie kaufen keinen Lottoschein, auf den wir gleich noch eingehen, sondern betreiben die Lotterie selbst.) Sie drucken 100.000 Tickets, die Sie für jeweils 1 Währungseinheit verkaufen. Eines dieser Tickets berechtigt den Käufer zu 40.000 Währungseinheiten.
Angenommen, Sie können alle Tickets verkaufen, verdienen Sie 60.000 Währungseinheiten: 100.000 Währungseinheiten im Verkauf abzüglich des Preises von 40.000 Währungseinheiten. Für Sie beträgt der Wert jedes Tickets 0,60 Währungseinheiten, die über alle Tickets abgeschrieben werden. Dies ist ein zuverlässiger Wert. Darauf können Sie sich verlassen. Wenn Sie es leid sind, die Tickets selbst zu verkaufen, und jemand kommt und anbietet, sie für jeweils 0,30 Währungseinheiten zu verkaufen, wissen Sie genau, wo Sie stehen.
Für den Lotteriekäufer ist die Situation anders. Der Käufer hat beim Kauf eines Lottoscheins einen erwarteten Verlust von 0,60 Währungseinheiten. Aber das ist wahrscheinlich: Der Käufer kann 30 Jahre lang jeden Tag zehn Lottoscheine kaufen (etwas mehr als 100.000), ohne jemals zu gewinnen. Oder sie kaufen eines Tages spontan ein einzelnes Ticket und gewinnen 39.999 Währungseinheiten.
Bei der Datenstrukturanalyse handelt es sich um den ersten Fall, bei dem wir die Kosten für eine Datenstrukturoperation (z. B. Einfügen) über alle Operationen dieser Art amortisieren. Die Durchschnittsfallanalyse befasst sich mit dem erwarteten Wert einer stochastischen Operation (z. B. Suche), bei der wir nicht die Gesamtkosten aller Operationen berechnen können, sondern eine probabilistische Analyse der erwarteten Kosten einer einzelnen Operation liefern können.
Es wird oft behauptet, dass eine amortisierte Analyse für die Situation gilt, in der eine kostenintensive Operation selten ist, und das ist häufig der Fall. Aber nicht immer. Betrachten Sie zum Beispiel die sogenannte "Banker-Warteschlange", eine FIFO-Warteschlange (First-In-First-Out), die aus zwei Stapeln besteht. (Es ist eine klassische funktionale Datenstruktur; Sie können billige LIFO-Stapel aus unveränderlichen, einfach verknüpften Knoten erstellen, aber billige FIFOs sind nicht so offensichtlich). Die Operationen werden wie folgt implementiert:
Nun behaupte ich, dass die amortisierten Kosten von
put
undget
sindO(1)
, vorausgesetzt, ich beginne und ende mit einer leeren Warteschlange. Die Analyse ist einfach: Ichput
gehe immer auf den rechten Stapel undget
vom linken Stapel. Abgesehen von derIf
Klausel ist jederput
einpush
und jederget
ein apop
, die beide sindO(1)
. Ich weiß nicht, wie oft ich dieIf
Klausel ausführen werde - es hängt vom Muster vonput
s undget
s ab -, aber ich weiß, dass sich jedes Element genau einmal vom rechten zum linken Stapel bewegt. Die Gesamtkosten über die gesamte Folge von nsput
und nsget
betragen also:push
ns, nspop
und nsmove
, wobei a amove
istpop
gefolgt von apush
: Mit anderen Worten, die 2n-Operationen (nsput
und nsget
) führen zupush
2ns und 2nspop
. Die fortgeführten Anschaffungskosten eines einzelnenput
oderget
sind einspush
und einspop
.Beachten Sie, dass Banker-Warteschlangen genau aufgrund der amortisierten Komplexitätsanalyse (und der Zuordnung des Wortes "amortisiert" zu Finanzen) so genannt werden. Die Warteschlangen von Banker sind die Antwort auf eine häufig gestellte Interviewfrage, obwohl ich denke, dass sie jetzt als zu bekannt angesehen wird: Überlegen Sie sich eine Warteschlange, die die folgenden drei Operationen in der amortisierten O (1) -Zeit implementiert:
1) Holen Sie sich das älteste Element der Warteschlange und entfernen Sie es.
2) Stellen Sie ein neues Element in die Warteschlange.
3) Ermitteln Sie den Wert des aktuellen Maximalelements.
quelle
Das Prinzip der "amortisierten Komplexität" ist, dass, obwohl etwas dabei ziemlich komplex sein kann, da es nicht sehr oft gemacht wird, es als "nicht komplex" betrachtet wird. Wenn Sie beispielsweise einen Binärbaum erstellen, der von Zeit zu Zeit ausgeglichen werden muss - beispielsweise einmal bei jeder
2^n
Einfügung -, da das Ausgleichen des Baums zwar recht komplex ist, jedoch nur einmal in n Einfügungen erfolgt (z. B. einmal bei Einfügungsnummer 256, dann erneut bei 512., 1024. usw.). Bei allen anderen Einfügungen ist die Komplexität O (1) - ja, es wird O (n) einmal alle n Einfügungen benötigt, aber es ist nur eine1/n
Wahrscheinlichkeit - also multiplizieren wir O (n) mit 1 / n und erhalten O (1). Das heißt also "Amortisierte Komplexität von O (1)" - denn wenn Sie weitere Elemente hinzufügen, ist der Zeitaufwand für das Neuausgleichen des Baums minimal.quelle
Amortisierte Mittel, aufgeteilt auf wiederholte Läufe. Das Worst-Case-Verhalten tritt garantiert nicht häufig auf. Wenn zum Beispiel der langsamste Fall O (N) ist, aber die Wahrscheinlichkeit, dass dies geschieht, nur O (1 / N) ist und andernfalls der Prozess O (1) ist, hätte der Algorithmus immer noch die konstante O (1) -Zeit amortisiert . Betrachten Sie einfach die Arbeit jedes O (N) -Laufs als auf N andere Läufe aufgeteilt.
Das Konzept hängt davon ab, dass genügend Läufe vorhanden sind, um die Gesamtzeit aufzuteilen. Wenn der Algorithmus nur einmal ausgeführt wird oder bei jeder Ausführung eine Frist einhalten muss, ist die Komplexität im schlimmsten Fall relevanter.
quelle
Angenommen, Sie versuchen, das k-te kleinste Element eines unsortierten Arrays zu finden. Das Sortieren des Arrays wäre O (n logn). Wenn Sie also die k-te kleinste Zahl finden, suchen Sie einfach den Index, also O (1).
Da das Array bereits sortiert ist, müssen wir nie wieder sortieren. Wir werden das Worst-Case-Szenario nie mehr als einmal treffen.
Wenn wir n Abfragen durchführen, um das k-te kleinste zu finden, ist es immer noch O (n logn), da es über O (1) dominiert. Wenn wir die Zeit jeder Operation mitteln, ist dies:
(n logn) / n oder O (logn). Also, Zeitkomplexität / Anzahl der Operationen.
Dies ist amortisierte Komplexität.
Ich denke, so geht es, ich lerne es auch nur ..
quelle
Es ist etwas ähnlich wie das Multiplizieren der Worst-Case-Komplexität verschiedener Zweige in einem Algorithmus mit der Wahrscheinlichkeit, diesen Zweig auszuführen und die Ergebnisse zu addieren. Wenn es also sehr unwahrscheinlich ist, dass ein Zweig genommen wird, trägt dies weniger zur Komplexität bei.
quelle