第一次实现:以下堆栈实现假定列表的末尾将保存堆栈的顶部元素。随着堆栈的增长,新项目将添加到列表的末尾。
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)。如果有,怎么样?
答案 0 :(得分:6)
列表经过优化,可以从最后添加和弹出。从列表的开头插入或删除项目要昂贵得多,因为需要移动所有项目。
Python确实有一个数据结构collections.deque
,它针对两端的附加进行了优化。
答案 1 :(得分:1)
在Python中,列表是使用可调整大小的其他对象引用数组实现的。
因此,列表末尾的push / popping元素比列表开头的push / popping更有效。
在数组的开头添加/删除元素非常昂贵,因为您必须将所有其他元素移到一个空间上。另一方面,假设在数组末尾有足够的空白空间,将元素添加/删除到数组的末尾是相对便宜的。
当数组已满时,Python将动态地为该数组的末尾分配更多内存,这很昂贵,但摊销的性能仍然非常出色。
答案 2 :(得分:0)
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)
`