Python中整数的O(1)可索引deque
我有什么选择?我需要调用大量的Python中整数的O(1)可索引deque,python,collections,Python,Collections,我有什么选择?我需要调用大量的appends(右端)和poplefts(自然是从左端),但也需要从存储的中间读取,这将根据算法的性质稳步增长。我希望所有这些操作都在O(1)中 我可以很容易地用C语言在循环寻址数组(单词是什么?)上实现它,当数组满时,它会自动增长;但是Python呢?指向其他语言的指针也很受欢迎(我意识到“collections”标记更面向Java等,并希望进行比较,但作为次要目标) 我有Lisp的背景,在Python中从列表中删除head元素是一个O(n)操作,这让我很惊讶。一
append
s(右端)和popleft
s(自然是从左端),但也需要从存储的中间读取,这将根据算法的性质稳步增长。我希望所有这些操作都在O(1)
中
我可以很容易地用C语言在循环寻址数组(单词是什么?)上实现它,当数组满时,它会自动增长;但是Python呢?指向其他语言的指针也很受欢迎(我意识到“collections”标记更面向Java等,并希望进行比较,但作为次要目标)
我有Lisp的背景,在Python中从列表中删除head元素是一个
O(n)
操作,这让我很惊讶。一个<代码> DeQue/代码>可能是一个答案,除了文档中所说的Access是中间的代码> o(n)< /代码>。是否还有其他预构建的内容?访问lisp列表的中间也是O(n)
Pythonlist
s是数组列表,这就是为什么弹出头部代价高昂(弹出尾部是固定时间)
你要找的是一个头部有(摊销)恒定时间删除的数组;这基本上意味着您必须在列表
上构建一个数据结构,该结构使用延迟删除,并且能够在队列为空时回收延迟删除的插槽
或者,使用一个哈希表和两个整数来跟踪当前连续的键范围。可能会对您有所帮助,尽管我不确定access是否为O(1)
您可以使用两个python列表来获得一个分期O(1)数据结构,一个保存deque的左半部分,另一个保存deque的右半部分。前半部分是反向存储的,因此deque的左端位于列表的后面。大概是这样的:
class mydeque(object):
def __init__(self):
self.left = []
self.right = []
def pushleft(self, v):
self.left.append(v)
def pushright(self, v):
self.right.append(v)
def popleft(self):
if not self.left:
self.__fill_left()
return self.left.pop()
def popright(self):
if not self.right:
self.__fill_right()
return self.right.pop()
def __len__(self):
return len(self.left) + len(self.right)
def __getitem__(self, i):
if i >= len(self.left):
return self.right[i-len(self.left)]
else:
return self.left[-(i+1)]
def __fill_right(self):
x = len(self.left)//2
self.right.extend(self.left[0:x])
self.right.reverse()
del self.left[0:x]
def __fill_left(self):
x = len(self.right)//2
self.left.extend(self.right[0:x])
self.left.reverse()
del self.right[0:x]
我不能100%确定这段代码和python列表的摊销性能之间的交互是否真的会导致每个操作的O(1),但我的直觉是这样说的。队列不支持访问队列的中间部分。我可以在O(n)时间内从列表的开头删除一个连续的范围吗?怎么做?@WillNess,但是……python程序员仍然使用哈希表。如果您试图在“H”下查找哈希表,那么我建议您按照教程(或阅读文档)学习python提供的功能。@WillNess如果您不知道如何删除列表的一部分,那么我绝对建议您遵循python教程。@WillNess,我会给您一个提示:字典。还有Marcin,您可能会更有用一些。@Willenss您没有费心学习使用基本类型的语法,甚至没有学习内置数据类型的存在。关于这个答案,您提出的两个问题的答案都是使用标准文档或介绍性材料来学习python。非常感谢,我会考虑一下的。
del self.right[0:x]
需要O(n)个时间吗?还有extend
?事实上,在这个算法中,我从不调用popright
和pushleft
,所以只要左侧用尽,我就用相反的右侧替换左侧。这太棒了!谢谢!是的,但是想法是,fill\u right
和fill\u left
只在每个O(n)操作中调用,因此每个操作都需要摊销O(1)时间。我很确定,除非大小是有界的(你在Q for a C实现中提到的调整大小也会使其成为O(n)最坏的情况),否则你所问的问题只能在摊销O(1)时间内实现。是的,我理解这一点,偶尔O(n)是好的(但比O(n)更坏,这是我的意思)。对不起,我不清楚。但是由于我从来没有调用过popright
和pushleft
,唯一一个耗尽精力的是left
,我将使用反向的right
!我将直接在代码中互换使用这两个列表。非常感谢你!代码q=mydeque();q、 左推(1);打印(q.popright())
崩溃,因为\u fill\u left
函数仅将1//2==0
元素从“左”列表传输到“右”列表。通常,这可能是相关的。