2015-09-11 7 views
5

Diese wiki.python.org Seite auf algorithmische Komplexität einiger Datenstrukturen sagt der folgende für ein collections.deque Objekt:Warum ist das Hinzufügen oder Entfernen von der Mitte eines collections.deque langsamer als das Nachschlagen?

A deque (Deque) wird intern als doppelt verknüpfte Liste dargestellt. (Nun, eine Liste von Arrays anstelle von Objekten, für mehr Effizienz.) Beide Enden sind zugänglich, aber selbst in der Mitte ist langsam, und Hinzufügen oder Entfernen von der Mitte ist noch langsamer.

Zwei Fragen:

1) ist das Hinzufügen zu der Mitte eines deque überhaupt möglich? Ich sehe keine Methode, dies in der API zu tun.

2) Warum sollte das Entfernen (oder Hinzufügen) langsamer sein als das Suchen in der Mitte eines deque? Es handelt sich um eine doppelt verknüpfte Liste. Daher sollte add/remove eine konstante Zeitoperation sein, sobald Sie das Objekt gefunden haben, das Sie hinzufügen möchten.

Antwort

3
  1. Es ist möglich, Gegenstände mit der remove()-Methode oder das del Schlüsselwort zu löschen. Das Einfügen von Elementen ist nicht möglich. (Die einzige Möglichkeit, dass einfügen würde in der API-Dokumentation nicht auftauchen würde slice Zuordnung sein, und das ist ungültig auf einem deque.)
  2. Denn, wie die Beschreibung sagt, es ist eigentlich eine doppelt verknüpfte Liste von Arrays. Das Einfügen oder Entfernen von Objekten könnte daher erfordern, dass Elemente von einem Array zu einem anderen verschoben werden. (Ich habe die Implementierung nicht angeschaut, aber ich weiß, dass deque eine Stride-Technik verwendet, wenn nach Elementen gesucht wird und ich nehme an, dass die Größe der verwendeten Arrays dieselbe ist wie die Schrittlänge, die 62 ist.) Sie müssten verschieben eine Menge Speicher in einem regulären list beim Löschen von Elementen, aber zumindest ist es alles in einem Stück und es kann effizient bewegt werden.
+0

Was Sie am Ende bedeuten, wenn Sie den Speicher für einen 'list' sagen„alle eins Brocken "? Python-Listen sind zusammenhängende Arrays * von Zeigern * nicht zusammenhängende Arrays * von Speicher *. Das heißt, die Zeiger sind zusammenhängend, aber was auch immer sie zeigen, kann überall sein, und es ist einer der Hauptgründe für gebrochenes Gedächtnis in Python. Denken Sie nur daran, Listenelement 2 willkürlich einem großen, vorab zugewiesenen Objekt zuzuweisen, wie 'my_list [1] = irgendein_Objekt'. Ich bin wahrscheinlich nur durch Ihre Formulierungen verwirrt, aber Sie sagen das sicher nicht alles von "my_lists" wird "memory" für das große 'some_object' herumgemischt? – ely

+0

Nein, ich meine nur, dass das Löschen oder Einfügen von Elementen in einer "Liste" nur das Verschieben eines einzelnen Speicherbereichs erfordert. Es sind die Zeiger, die bewegt werden, stimmt. – kindall

+0

Gotcha, danke für die Klärung. Für alle anderen, die auf diese Kommentare stolpern, verweise ich grundsätzlich auf die Erklärung aus Jake VanderPlas Artikel ["Warum Python langsam ist"] (https://jakevdp.github.io/blog/2014/05/09/why-python- is-slow /), speziell in Abschnitt 3 des Objektmodells. – ely

1

1) Sieht aus wie deque.insert() 3,5

2) Von der Quelle in Python wurde hinzugefügt: https://github.com/python/cpython/blob/d16a1520c2b22c3cbde7547937ba283db3e88ff5/Modules/_collectionsmodule.c#L952-L958

insert(),() entfernen, und delitem() werden in Form umgesetzt von rotieren() zur Vereinfachung und angemessene Leistung gegen Ende Punkte. Wenn aus irgendeinem Grund diese Methoden populär werden, ist es nicht schwer, dies unter Verwendung direkter Datenbewegung (ähnlich der Code in Listen Slice-Zuweisungen) wieder zu implementieren und eine Leistung Boost zu erreichen (durch Verschieben jedes Zeigers nur einmal statt zweimal).

Der Grund, warum es langsamer ist, ist, wie es implementiert wurde.

+1

Huh, also was ist diese 'deque.insert' Funktion? Wie nenne ich es? –

+0

@EliRose. Es gibt keine Einfügemethode –

+0

@PadraicCunningham Sinn macht, ich habe es gerade versucht und die Methode existiert nicht. Worüber spricht dieser Kommentar in der Quelle? –

2

Es ist möglich, mit python3.5 einzufügen. index(), insert(), and copy() sind drei neue Methoden nur in python3.5, new in python 3.5, gibt es keine Möglichkeit, in eine deque in früheren Versionen einzufügen:

Die Deque-Klasse definiert nun Index(), einfügen() und copy(), wie sowie unterstützt + und * Betreiber. Dadurch können Deques als MutableSequence erkannt und ihre Substituierbarkeit für Listen verbessert werden. (Beitrag von Raymond Hettinger, Ausgabe 23704.)

Sie können aus der Mitte eines Deque entfernen, entweder mit del oder deque.remove:

deq = deque([1,2,3,4,5,6]) 
del deq[4] 
deq.remove(3) 
+0

upvote, für die Erwähnung der neuen Methoden, aber es beantwortet die Frage nicht. – jfs

+0

Sie sind neu in Python 3.5, nicht 3.6. – wim