Der Standard sagt:
Eine Deque ist ein Sequenzcontainer, der Iteratoren mit wahlfreiem Zugriff unterstützt (27.2.7). Darüber hinaus werden Einfüge- und Löschvorgänge mit konstanter Zeit am Anfang oder am Ende unterstützt. Einfügen und Löschen in der Mitte dauert linear.
In derselben Klausel heißt es jedoch auch:
Alle Komplexitätsanforderungen in dieser Klausel werden ausschließlich in Bezug auf die Anzahl der Operationen an den enthaltenen Objekten angegeben. [Beispiel: Der Kopierkonstruktor vom Typ
vector<vector<int>>
hat eine lineare Komplexität, obwohl die Komplexität des Kopierens jedes enthaltenenvector<int>
selbst linear ist. - Beispiel beenden]
Bedeutet dies nicht, dass das Einfügen zu Beginn beispielsweise deque<int>
eine lineare Zeit in Anspruch nehmen darf, solange nicht mehr als eine konstante Anzahl von Operationen an den int
s ausgeführt wird, die sich bereits in der Deque befinden, und an dem das neue int
Objekt eingefügt wird ?
Angenommen, wir implementieren eine Deque unter Verwendung eines "Vektors der Größe-K-Vektoren". Es scheint, dass einmal alle K-mal, die wir am Anfang einfügen, am Anfang ein neuer Vektor der Größe K hinzugefügt werden muss, sodass alle anderen Vektoren der Größe K verschoben werden müssen. Dies würde bedeuten, dass die zeitliche Komplexität des Einfügens zu Beginn O (N / K) amortisiert wird, wobei N die Gesamtzahl der Elemente ist, K jedoch konstant ist, so dass dies nur O (N) ist. Es scheint jedoch, dass der Standard dies zulässt, da durch das Verschieben eines Vektors der Größe K keines seiner Elemente verschoben wird und die "Komplexitätsanforderungen" "nur in Bezug auf die Anzahl der Operationen" für die enthaltenen int
Objekte angegeben werden.
Erlaubt der Standard dies wirklich? Oder sollten wir es als eine strengere Anforderung interpretieren, dh eine konstante Anzahl von Operationen an den enthaltenen Objekten plus eine konstante zusätzliche Zeit?
vector<vector<int>>
aber dann linear in Bezug auf die Elemente des Inneren verwendetvector<int>
. Wenn Sie nur die Anzahl der Elemente des äußeren Vektors berücksichtigen, würde ich das Kopieren des inneren Vektors als konstant betrachten, obwohl ich mich möglicherweise irre, ist es hier schon spätAntworten:
Das wäre keine gültige Implementierung. Das Einfügen an der Vorderseite eines
vector
ungültig macht alle Zeiger / Referenzen im Container.deque
ist erforderlich, um keine Zeiger / Referenzen beim Einfügen von vorne ungültig zu machen .Aber lassen Sie uns das jetzt ignorieren.
Ja, das wäre erlaubt. In der Tat sind reale Implementierungen von
deque
nicht so unähnlich (obwohl siestd::vector
sich aus offensichtlichen Gründen nicht selbst verwenden). Der Grundriss einerdeque
Implementierung besteht aus einer Reihe von Zeigern auf Blöcke (mit Platz für Wachstum sowohl vorne als auch hinten), wobei jeder Block bis zu X Elemente sowie Zeiger auf die nächsten / vorherigen Blöcke enthält (um einzelne Blöcke zu erstellen). Elementiteration schnell).Wenn Sie vorne oder hinten genügend Elemente einfügen, muss das Array der Blockzeiger wachsen. Dies erfordert eine Operation, die eine lineare Zeit im Verhältnis zur Anzahl der Elemente in der ist
deque
, aber nicht tatsächlich für die Elemente selbst ausgeführt wird, sodass sie nicht zählt. Die Spezifikation hat nichts über die Komplexität dieser Operation zu sagen.Ohne diese Bestimmung bin ich mir nicht sicher, ob der einzigartige Funktionsumfang
deque
(schnelles Einfügen von Vorder- und Rückseite und Direktzugriff) implementiert werden kann.quelle
vector
die Implementierung der automatischen Größenänderung nur eine konstante Anzahl zusätzlicher Elemente hinzugefügt würde, wäre das Einfügen keine "amortisierte Konstante". Es geht also nicht nur darum, Platz zu haben. Sie müssen jedes Mal mehr Platz einfügen .deque
Anforderungen, dass jede Einfügung in Bezug auf die Anzahl der Elemente im Container "amortisiert konstant" ist. Sie ist nur in Bezug auf die Anzahl der Operationen an Elementen im Container konstant.Ich denke, Sie erreichen ein wenig, wie Sie die Bedeutung von Komplexitätsdomänen interpretieren. Sie versuchen, zwischen "linearer Zeit" und "linearer Komplexität" zu unterscheiden, von der ich nicht überzeugt bin, dass sie viel Sinn macht.
Der Standard ist klar, dass das Einfügen an der Vorderseite zeitlich konstant ist, und ich denke, wir sind uns alle einig. Die letztere Passage sagt uns nur, dass das, was jede dieser "konstanten" Mengen von Operationen darunter beinhaltet, einfach nicht durch den Standard spezifiziert oder eingeschränkt wird.
Und das ist nicht ungewöhnlich. Jeder Algorithmus arbeitet auf einer gewissen Abstraktionsbasis. Selbst wenn wir einen Algorithmus schreiben würden, der auf einzelne Maschinenanweisungen hinausläuft, und wir sagten, dass immer nur N Maschinenanweisungen von unserem Algorithmus generiert wurden, würden wir nicht untersuchen, welche Art von Komplexität jede einzelne Komplexität im Prozessor und hat Fügen Sie das zu unseren Ergebnissen hinzu. Wir würden nicht sagen, dass einige Operationen auf quantenmolekularer Ebene mehr bewirken und unser O (n) -Algorithmus daher tatsächlich O (N × M 3 ) oder so ist. Wir haben uns entschieden, diese Abstraktionsebene nicht zu berücksichtigen. Und wenn diese Komplexität nicht von den Eingaben des Algorithmus abhängt, ist das völlig in Ordnung.
In Ihrem Fall ist die Größe der verschobenen / kopierten inneren Vektoren nicht wirklich relevant, da sich diese nicht von Natur aus ändern, wenn die Deque wächst. Die Anzahl der inneren Vektoren reicht aus, aber die Größe jedes einzelnen ist eine unabhängige Eigenschaft. Daher ist es irrelevant, die Komplexität des Einfügens eines neuen Elements in den äußeren Vektor zu beschreiben.
Variiert die tatsächliche Ausführungszeit (die selbst in einigen algorithmischen Begriffen beschrieben werden könnte, wenn Sie dies wünschen) in Abhängigkeit vom Inhalt der kopierten inneren Vektoren? Ja natürlich. Dies hat jedoch nichts damit zu tun, wie die Aufgabe, den äußeren Vektor zu erweitern, in der Arbeitslast wächst, wenn der äußere Vektor selbst wächst.
Hier sagt der Standard also, dass er nicht N oder N 2 kopiert oder sogar N innere Vektoren protokolliert , wenn Sie einen anderen vorne platzieren. Es heißt, dass sich die Anzahl dieser Operationen nicht ändern wird, wenn Ihre Deque wächst. Es heißt auch, dass es für die Zwecke dieser Regel egal ist, was das Kopieren / Verschieben der inneren Vektoren tatsächlich beinhaltet oder wie groß sie sind.
Bei der Komplexitätsanalyse geht es nicht um Leistung. Bei der Komplexitätsanalyse geht es darum, wie die Leistung skaliert.
quelle