栈node
栈和队列是两个很基础的数据结构python
通常栈有两个概念:数据结构
(1)栈区(内存中)app
(2)LIFO(Last In First Out)ide
栈最好的理解方式,能够理解为一个桶,往桶里放盘子,拿出来的时候只能从顶上开始拿。函数
data
单元测试
ADT {测试
method { pushui
pop
spa
上一节实现了先进先出的循环双端队列(Deque),支持双向的push/pop操做,只要实现了Deque就很容易实现栈。
其实用 python 的内置类型 collections.deque 来实现它也很简单。
用Deque实现stack
先继承以前写的 CircualDoubleLinkedList() 类,经过继承的方式实现Deuqe,以下:
class Deque(CircualDoubleLinkedList): def pop(self): if len(self) == 0: #若是队列为空 raise Exception('empty') tailnode = self.tailnode() #定义尾节点 value = tailnode.value #尾节点的值 self.remove(tailnode) #删除尾节点,O(1) return value #返回删除节点的value def popleft(self): #另一种从左侧删除的方法 if len(self) == 0: raise Exception("empty") headnode = self.headnode() value = headnode.value self.remove(headnode) return value class Stack(): def __init__(self): self.deque = Deque() #使用内置库的collections.deque方法更容易实现 def push(self, value): return self.deque.append(value) def pop(self, value): return self.deque.pop(value) def __len__(self): return len(self.deque) def is_empty(self): return len(self) == 0 #单元测试 def test_stack(): s = stack() for i in range(3): s.push(i) assert len(s) == 3 assert s.pop() == 2 assert s.pop() == 1 assert s.pop() == 0 assert s.is_empty() import pytest with pytest.raise(Exception) as excinfo: s.pop() assert "empty" in str(excinfo.value)
栈溢出(Stack over flow)
栈有两个主要的使用含义:
1.数据结构上所说的后进先出的结构
2.内存结构的栈区
当写递归函数的时候,每一层的递归函数都会用栈区来存储每一层函数它的变量值,若是写了一个没有出口的递归函数,就会致使栈溢出。
演示栈溢出:
#栈溢出 def infinite_fib(n): return infinite_fib(n-1) + infinite_fib(n-2) #执行这个函数后,会返回异常 if __name__ == "__main__": infinite_fib(10)
出现栈溢出是由于内存分配给栈区的大小是固定的,当写了一个无穷递归的函数,栈空间很快就会被用完,就会抛出builtins.RecursionError: maximum recursion depth exceeded的栈异常。
因此写递归必定要注意必需要有递归出口,这也是写递归函数的坑。
最后,建议看看内置库collections.deque的实现,有轮子直接拿来用,就简单多了。