std: container c++ - "move to front"
Ich bin auf der Suche nach einem container wie std eine std::list, die effizient bewegen können ein element auf der Vorderseite:
a-b-c-d-e
bewegen "b" nach vorne:
a-c-d-e-b
Gibt es keine solche Funktion im std-Container. Dafür, ich glaube, ich muss kombinieren, entfernen und push_front Funktion hat aber kann jemand eine bessere Idee?
Danke im Voraus.
- Was bedeutet "effizient" bedeuten?
- goode Frage ... ich meine, besser als zu entfernen es und schaffen es an die Spitze. Wenn ich hatte, es zu implementieren, von Grund auf (in C), ich könnte einfach machen.Nächster Punkt "c", c.prev Punkt "a", b.prev Punkt "e", b.Nächster Punkt die NULL, vorne Punkt "b" und e.Nächster Punkt "b"... das wäre effizient, aber re-Implementierung von container ist ein bisschen zu aufwendig 😉
- Die "fast" - Liste-Lösung verändert sich viel von Zeigern (8 bytes in 64-bit-code) an zufällige Positionen in potentiell nicht-Cache-Speicher. Ein Vektor mit fünf Elementen (wie im Beispiel), wird sich möglicherweise passen in eine einzige cache-Zeile, und sehr schnell.
InformationsquelleAutor Jav | 2013-01-29
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie nicht haben, um halten Sie die Reihenfolge der anderen Elemente,
dann die einfachste Lösung ist sicherlich einfach tauschen
gewünschte element mit dem ersten element in den container. Diese
werden effizient mit alle Container.
Ansonsten
std::list
bietet einesplice
Betrieb könnteverwendet werden. So etwas wie die folgenden, ich denke:
Diese sollten am Ende mit nur ein paar Zeiger-Operationen, und
keine kopiert. Auf der anderen Seite
std::list
kann sehr langsam sein inallgemein (wegen dem schlechten Lokalität); ich würde Messen sehr
gezielt gegen die naive Implementierung mit
std::vector
,um sicherzustellen, dass es war ein Sieg weltweit. Die Beseitigung aller Kopien hier
kann nicht ein Gewinn sein, wenn die Iteration zu finden das element, das Sie möchten
nach vorne bewegen, ist zehn mal teurer. (Eine Menge von dieser
hängt davon ab, wie teuer
MyType
zu kopieren, und wie groß ist esist. Wenn
sizeof(MyType)
ist nah an die Größe einer Seite, oderZugriff auf
MyType
landet Zugriff auf eine Menge von indirektzugewiesenen Objekte, die Lokalität argument nicht halten.)
Mit einem
std::vector
, anstatt die offensichtlicheerase
/insert
Dadurch werden weniger Exemplare als von den
erase
(die Kopienalle folgenden Elemente)
insert
(der kopiert auch allesdie folgenden Elemente, was bedeutet, dass alle Elemente,
weil wir das einfügen am Anfang) Muster.
list.front() = tmp
statt*list.begin() = tmp
?Auf
std::vector
könnten Siestd::rotate
, die hat lineare KomplexitätAuf eine
std::list
Sie könnte verwenden Sie die member-Funktionsplice
, die (gegebenen Iteratoren) hat Konstante KomplexitätHINWEIS: das Letzte element ist conventially bezeichnet als
back
im STL-Containern, und das erste element alsfront
. Fürstd::vector
bekommen Iteratoren zu einem bestimmten element ist in konstanter Zeit, und tauschen ist die lineare Zeit. Fürstd::list
bekommen Iteratoren ist die lineare Zeit, aber Spleißen in der gleichen Liste ist in konstanter Zeit. Allerdings viel besser, memory-caching-Verhalten des Vektors ist auch wichtig, da dieser benchmark von Stroustrup zeigt.UPDATE: Mehrere Kommentatoren erwähnten Austausch der Elemente: dies gilt nur, wenn Sie transformieren möchten
a-b-c-d-e
ina-e-c-d-b
. Verwenden Sie In diesem Fallstd::iter_swap
auf alle container, die Sie mögen. Für die transformation vona-b-c-d-e
ina-c-d-e-b
verwendenstd::rotate
oderlist::splice
.std::list
und ein entfernen-und-push " - operation haben Konstante Komplexität...std::list
und einfügen woanders ist wirklich sehr Billig. Ich wäre sehr überrascht, wenn diestd::vector
Umsetzung war schneller außer für pathologische Fälle.std::vector
.std::list
, dann einsetzen in den Kopf, werden zwei Kopien des Elements, plus, eine freie und eine Zuteilung. Freigeben und zuweisen von Speicher können leicht Kosten mehr Zeit als es dauert, das kopieren von ein paar hundertint
oderdouble
. Für eine Sammlung von weniger als tausendint
,std::vector
wird wahrscheinlich schlagenstd::list
für diese operation. Auch eine Lösung mit Würze wird wahrscheinlich berühren mehrere verschiedene Seiten, wo wie bei kleineren Datensätzen, die Lösung mitvector
vielleicht nie verlassen haben, ein cache-miss.rotate
Lösung ändert sich die Reihenfolge der übrigen Elemente. Wenn dies akzeptabel ist, nur vertauschen mit dem ersten element ist wesentlich effizienter.std::rotate
dreht sich das gesamte Teilbereiche. siehe liveworkspace.org/code/QItmN$17 0,1,2,3,4 Sequenz gedreht, in 0,2,3,4,1. Dies ist genau die Art von transformation, die die OP beantragt. Siehe update zu beantworten.