Python中的高效堆栈实现

Posted

技术标签:

【中文标题】Python中的高效堆栈实现【英文标题】:Efficient Stack implementation in Python 【发布时间】:2015-09-22 15:53:34 【问题描述】:

第一次实现:以下堆栈实现假定列表的末尾将包含堆栈的顶部元素。随着堆栈的增长,新项目将被添加到列表的末尾。

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self, item):
        self.items.append(item)

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

    def peek(self):
        return self.items[len(self.items)-1]

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

第二个实现:第二个实现假设列表的开头包含堆栈的顶部元素,并且在索引 0 处添加新项目。

 class Stack:
     def __init__(self):
         self.items = []

     def isEmpty(self):
         return self.items == []

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

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

     def peek(self):
         return self.items[0]

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

作为数据结构的初学者,我想知道: 1. 哪种实现在时间或空间方面更有效,为什么? 2. 是第二次实现中insert(0) 的时间复杂度 O(n)。如果是,如何?

【问题讨论】:

见wiki.python.org/moin/TimeComplexity。请注意,self.items[-1] 会为您提供最后一个元素较少的问题。 是的,先重写你的peek方法。并称之为 tos,也许(栈顶) 感谢@jonrsharpe 提供链接。 【参考方案1】:

列表已针对从末尾追加和弹出进行了优化。从列表的开头插入或删除项目的成本要高得多,因为所有项目都需要移动。

Python 确实有一个数据结构 collections.deque,它针对在两端追加进行了优化。

【讨论】:

【参考方案2】:

在 Python 中,列表是通过可调整大小的对其他对象的引用数组来实现的。

见How are lists implemented?

因此,在列表末尾推送/弹出元素将比在列表开头推送/弹出更有效。

在数组的开头添加/删除元素非常昂贵,因为您必须将所有其他元素移动到一个空格上。另一方面,假设数组末尾有足够的空白空间,在数组末尾添加/删除元素相对便宜。

当数组已满时,Python 会动态地为该数组的末尾分配更多内存,虽然代价高昂,但摊销后的性能仍然非常出色。

【讨论】:

【参考方案3】:
def __init__(self):
  self.items=[]
def push(self,item):
  self.items.append(item)
def pop(self):
  return self.items.pop()
def isEmpty(self):
  return self.items==[]
def peek(self):
  return self.items[len(self.items)-1]
def size(self):
  return len(self.items)

`

【讨论】:

以上是关于Python中的高效堆栈实现的主要内容,如果未能解决你的问题,请参考以下文章

万能的list列表,python中的堆栈队列实现全靠它!

高效实现:Java 中的“Python For Else Loop”

python中的堆栈跟踪和异常处理

使用高效的 `has` 操作实现堆栈

使用两个堆栈 Python 实现一个队列

Leetcode刷题Python155. 最小栈