Python中队列实现之间的区别

时间:2016-11-02 13:32:35

标签: python queue

其中一个exercises(即#6)要求我们比较队列实现的性能(头部在beinning /列表的末尾)。这听起来可能有些不同,所以我试着想出来。这是我的代码

import timeit

class QueueStart(object):
    '''Queue implementation with head in the beginning of a list'''    
    def __init__(self):
        self.items = []

    def enqueue(self, i):
        self.items.append(i)

    def dequeue(self):
        return self.items.pop(0)

    def isEmpty(self):
        return len(self.items) == 0

    def size(self):
        return len(self.items)

class QueueEnd(object):
    '''Queue implementation with head at the end of a list'''     
    def __init__(self):
        self.items = []

    def enqueue(self, item):
        self.items.insert(0, item)

    def dequeue(self):
        return self.items.pop()

    def isEmpty(self):
        return len(self.items) == 0

    def size(self):
        return len(self.items)

# store results for further plotting
start_add_list = [] # QueueStart.enqueue(item) runtimes for inputs of different sizes
start_pop_list = [] # the same for QueueStart.dequeue(item)
end_add_list = [] # the same for QueueEnd.enqueue(item) 
end_pop_list = [] # the same for QueueEnd.dequeue(item) 

for i in range(100000, 500000, 10000):
    qs = QueueStart()
    qs.items = list(range(i))
    qe = QueueEnd()
    qe.items = list(range(i))
    start_add = timeit.Timer('qs.enqueue(1)', 'from __main__ import qs')
    start_pop = timeit.Timer('qs.dequeue()', 'from __main__ import qs')
    end_add = timeit.Timer('qe.enqueue(1)', 'from __main__ import qe')
    end_pop = timeit.Timer('qe.dequeue()', 'from __main__ import qe')

    start_add_list.append(start_add.timeit(number=1000))
    start_pop_list.append(start_pop.timeit(number=1000))
    end_add_list.append(end_add.timeit(number=1000))
    end_pop_list.append(end_pop.timeit(number=1000))

以下是反映我的实验结果的情节 enter image description here enter image description here

众所周知insertpop(index)是O(n)。但有趣的是,从图表中我们看到insert(0, item)的时间是pop(0)的两倍。那个观察让我很奇怪,为什么会这样。从表面上看,两种方法看起来非常相似,但显然,引擎盖下有一些有趣的东西。所以,问题是:你能帮我解决一下吗?

1 个答案:

答案 0 :(得分:0)

关于CPython的list实施的一些阅读:http://www.laurentluce.com/posts/python-list-implementation/

基本上,列表的设计内存大约是他们在任何给定时间所需的内存的两倍,因此它们可以稍微改变长度,而无需重新分配内存。当列表需要更多内存时,它们有时需要将整个列表移动到内存中具有足够空间的另一个位置。当它们缩小时,它们可以在列表末尾释放内存。