问题
This wiki.python.org page on algorithmic complexity of some data structures says the following for a collections.deque
object:
A deque (double-ended queue) is represented internally as a doubly linked list. (Well, a list of arrays rather than objects, for greater efficiency.) Both ends are accessible, but even looking at the middle is slow, and adding to or removing from the middle is slower still.
Two questions:
1) Is adding to the middle of a deque
even possible? I don't see any method to do so in the API.
2) Why would removing (or adding) be slower than lookup in the middle of a deque
? It's a doubly-linked list, so add/remove should be a constant time operation once you've found the object you want to add.
回答1:
- It's possible to delete items using the
remove()
method or thedel
keyword. It's not possible to insert items. (The only possible way to insert that wouldn't show up in the API documentation would be slice assignment, and that's invalid on adeque
.) - Because, as the description says, it's actually a doubly-linked list of arrays. So inserting or removing things could require elements to be moved from one array to another. (I haven't looked at the implementation, but I know
deque
uses a stride technique when looking for elements and I assume the size of the arrays used is the same as the stride length, which is 62.) You'd have to shift a lot of memory around in a regularlist
when deleting items, too, but at least it's all in one chunk and it can be moved efficiently.
回答2:
It is possible to insert with python3.5. index(), insert(), and copy()
are three new methods only available in python3.5
, new in python 3.5, there is no way to insert into a deque in earlier versions:
The deque class now defines index(), insert(), and copy(), as well as supports
+
and*
operators. This allows deques to be recognized as a MutableSequence and improves their substitutability for lists. (Contributed by Raymond Hettinger issue 23704.)
You can remove from the middle of a deque, either using del
or deque.remove
:
deq = deque([1,2,3,4,5,6])
del deq[4]
deq.remove(3)
回答3:
1) Looks like deque.insert()
was added in Python 3.5
2) From the source: https://github.com/python/cpython/blob/d16a1520c2b22c3cbde7547937ba283db3e88ff5/Modules/_collectionsmodule.c#L952-L958
insert(), remove(), and delitem() are implemented in terms of rotate() for simplicity and reasonable performance near the end points. If for some reason these methods become popular, it is not hard to re-implement this using direct data movement (similar to the code used in list slice assignments) and achieve a performance boost (by moving each pointer only once instead of twice).
The reason it's slower is because of how it was implemented.
来源:https://stackoverflow.com/questions/32530065/why-is-adding-to-or-removing-from-the-middle-of-a-collections-deque-slower-than