有人知道Python(可能是2.7)是否有内置的linkedList
数据结构?我知道队列是使用list实现的,并且没有堆栈(有LIFO队列)。
答案 0 :(得分:9)
是的,Python的collections module提供了C实现的deque
对象,它在内部使用了BLOCK
的链接列表。
typedef struct BLOCK {
struct BLOCK *leftlink;
PyObject *data[BLOCKLEN];
struct BLOCK *rightlink;
} block;
typedef struct {
PyObject_VAR_HEAD
block *leftblock;
block *rightblock;
Py_ssize_t leftindex; /* 0 <= leftindex < BLOCKLEN */
Py_ssize_t rightindex; /* 0 <= rightindex < BLOCKLEN */
size_t state; /* incremented whenever the indices move */
Py_ssize_t maxlen; /* maxlen is -1 for unbounded deques */
PyObject *weakreflist;
} dequeobject;
static PyTypeObject deque_type;
答案 1 :(得分:3)
除非您确实需要针对特定内容的显式链接列表结构,否则Python的内置列表具有您从链接列表中获得的所有功能。例如,您可以将其用作堆栈,如下所示:
>>> x = []
>>> x.append(1)
>>> x.append(2)
>>> x
[1, 2]
>>> x.pop()
2
>>> x
[1]
>>>
或者,在给定元素之后插入元素:
>>> x = [1,2,3,4,5,6,7]
>>> x.insert(3,"a")
>>> x
[1, 2, 3, 'a', 4, 5, 6, 7]
>>>
例如,请参阅data structures上的Python文档。
但是,这是使用“list”抽象数据类型(ADT)。相反,“链表”不是ADT,而是实现该ADT的许多可能方式之一。
如果前置效率是一个问题,ŁukaszRogalski的答案指出collections.deque
是使用链表实现的。正如Using Lists as Queues所述:
也可以使用列表作为队列,其中添加的第一个元素是检索到的第一个元素(“先进先出”);但是,列表不能用于此目的。虽然列表末尾的追加和弹出快速,但从列表的开头进行插入或弹出是很慢的(因为所有其他元素都必须移动一个)。
要实现队列,请使用collections.deque,它设计为具有快速追加和两端弹出。
为了测试使用list
与deque
的效率影响,我使用了以下程序:
import timeit, sys
print ("append to list: %f" % (timeit.timeit ('x.append("x")', 'x = ["y"]')))
print ("insert to list element 0: %f" % (timeit.timeit ('x.insert(0,"x")', 'x = ["y"]')))
print ("append to deque: %f" % (timeit.timeit ('x.append("x")', 'import collections; x = collections.deque(["a","b","c"])')))
print ("append left to deque: %f" % (timeit.timeit ('x.appendleft("x")', 'import collections; x = collections.deque(["a","b","c"])')))
if (sys.version_info[0]+sys.version_info[1]/10) > 3.4999:
print ("insert in deque: %f" % (timeit.timeit ('x.insert(2,"x")', 'import collections; x = collections.deque(["a","b","c"])')))
...并获得了Python 3.6和Python 2.7的以下结果:
$ python3 testList.py
append to list: 0.113031
insert to list element 0: 191.147079
append to deque: 0.058606
append left to deque: 0.064640
insert in deque: 0.160418
$ python testList.py
append to list: 0.102542
insert to list element 0: 191.128508
append to deque: 0.083397
append left to deque: 0.064534
因此,list
大约需要两倍的时间来追加元素deque
和deque
花费更少的时间来预先添加(即附加到左侧)而不是追加。
答案 2 :(得分:2)
python中没有内置的链表,但是你可以使用dequeue,它既可以访问头部也可以是尾部,但如果你想实现你自己的链表可能是你可以使用
答案 3 :(得分:1)
我相信集合包中的deque类是作为双向链表实现的,具有头部和尾部保护。它支持默认列表的所有常用API。要附加到头部,请使用leftappend
功能。
from collections import deque
答案 4 :(得分:0)
Python有collections.deque,它是小list()的双向链接列表。
尽管使用Python list()而不是链接列表,几乎总是更好。即使链表在某些操作上具有出色的big-O,但由于引用的位置更好,所以list()常常会更快。
我实际上在Python中玩了链表: http://stromberg.dnsalias.org/~strombrg/linked-list/ ...在进行性能比较之前。
我使用“计数”程序作为测试平台;与链表相比,它比使用list()的版本更慢并且使用了更多的RSS(RAM)。计数为http://stromberg.dnsalias.org/~strombrg/count.html 我扔掉了它的链表版本。它并不是非常有用。
某种意义上说list()有时会更快。考虑在list()和链表中从第一个元素到最后一个元素进行遍历。 list()倾向于对n个元素引用执行单个RAM缓存命中,而链接列表倾向于对每个元素进行单个RAM缓存命中。这是因为list()引用在RAM中彼此相邻,但是链接的列表引用对于每个值都在不同的类实例中。缓存要比常规RAM快得多,这可能会很重要。
collections.deque并不会因此而牺牲太多,因为组成链表中每个节点的数组很小。
另一方面,如果要避免人们使用随机访问值的集合,则链表可能是一个好主意。也就是说,有时为了抽象起见,您可能更喜欢链表而不是list()。但是Python开发人员倾向于假设“我们都是成年人”。
此外,如果您已经知道将新值放在哪里(即,不需要O(n)搜索来确定将其放在哪里),则插入列表的中间,这是一个链表更快一点。