Why is adding to or removing from the middle of a collections.deque slower than lookup there?

无人久伴 提交于 2021-02-20 06:30:47

问题


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:


  1. It's possible to delete items using the remove() method or the del 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 a deque.)
  2. 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 regular list 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!