collections.deque(双向链表的实现)
deque: deque是(double-ended queue)的缩写,读作"deck",底层机制是双向链表。
python内置的list的优势是足够灵活,根据索引快速访问一个元素,支持切片访问。 但list本质是一个连续的内存区域,当列表在追加元素的时候,有时候需要额外分配内存(动态分配内存有个内部机制,并不是每增加一个元素都需要做一次额外分配内存)。
当pop掉末尾元素时,也同样可能需要移除一个内存块。当从最左侧插入一个元素时,后面的元素都要依次移动一个位置,性能很差。
而deque做为一种双向链表的实现,在两端追加或删除元素的效率都非常高。但也有不足的地方,比如使用下标访问的速度不如list快,且不支持切片。 而两种类型在插入或移除处于中间位置的元素时,性能差不多。
由于deque的这种特性,使得它特别适合实现队列(queue)和栈(statck)。虽然deque本身是线程安全的,但是由于其某些方法并不是线程安全的,所以如果想在多线程下使用队列或栈,请使用python内置的queue模块。
deque([iterable[, maxlen]]): 使用一个iterable来构造一个deque,可以指定一个长度,如果iterable的长度超出了maxlen,那么只会保留最后maxlen长度的iterable元素。
import string
from collections import deque
print(string.ascii_lowercase) # abcdefghijklmnopqrstuvwxyz
que = deque(string.ascii_lowercase, 10)
print(list(que)) # ['q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
appendleft(x): 从左侧追加一个元素。append与list的功能相同,都是从右侧追加一个元素。
popleft(): 从左侧移除一个元素。pop函数与list里的pop功能相同,是从右侧移除一个元素。有一点不同的是,不提供位置参数。
extendleft(iterable): 从左侧追加一组元素。
from collections import deque
lst = 'abcdefg'
dq = deque(lst)
print(list(dq)) # ['a', 'b', 'c', 'd', 'e', 'f', 'g']
dq.extendleft("hijk")
print(list(dq)) # ['k', 'j', 'i', 'h', 'a', 'b', 'c', 'd', 'e', 'f', 'g']
由于extendleft相当于是循环一个iterable执行appendleft方法,所以可以看到元素是以与iterable相反的顺序添加到deque里的。
rotate(n=1): 相当于把deque当成一个闭环,当n是正数时,将链表的每个元素向右移动n步,最右边的元素会依次接到最左边。当n是负数时,则是向左移动。
from collections import deque
lst = 'abcdefg'
dq = deque(lst)
print(list(dq)) # ['a', 'b', 'c', 'd', 'e', 'f', 'g']
dq.rotate(3)
print(list(dq)) # ['e', 'f', 'g', 'a', 'b', 'c', 'd']
其他支持的方法都与list方法功能一致:clear(), copy(), count(x), index(x[, start[, stop]]), insert(i, x), remove(value), reverse()
链表的性能
链表不是一块连续的内存地址,每个元素相当于一个节点,节点中会记录下一节点的内存地址。但链表本身会记录其头部节点和属部节点的地址,就像列表会在其创建后及每次增删元素时动态维护其长度一样。
链表虽能记住头尾节点的内存地址,但通过index访问一个元素时,它只能通过遍历,因此元素访问效率不如列表。
链表在头部插入和删除元素性能远高于列表,因为列表需要在内存中移动后面的元素位置。而在尾部增删元素的性能与列表差不多。
在数据量较大时,链表在中部增删元素的性能也好于列表。 虽然列表在通过下标定位的阶段速度很快,但增删元素后导致后面元素的内存位置移动就非常慢。 而链表虽然需要通过遍历才能定位到要增删的位置,但随后的操作只是更改前后节点的指向,整体性能更好。
如果只是遍历,那么链表和列表的性能相同,时间复杂度都是O(n)。
成员检测 a in list 因为需要遍历,所以效率不高。O(n)

浙公网安备 33010602011771号