📜  Python中的堆栈

📅  最后修改于: 2022-05-13 01:55:06.292000             🧑  作者: Mango

Python中的堆栈

堆栈是一种线性数据结构,它以后进/先出 (LIFO) 或先进/后出 (FILO) 方式存储项目。在堆栈中,在一端添加一个新元素,仅从该端移除一个元素。插入和删除操作通常称为推送和弹出。

python中的堆栈

与栈相关的函数有:

  • empty() – 返回栈是否为空 – 时间复杂度:O(1)
  • size() – 返回栈的大小 – 时间复杂度:O(1)
  • top() – 返回对栈顶元素的引用 – 时间复杂度:O(1)
  • push(a) - 在栈顶插入元素 'a' - 时间复杂度:O(1)
  • pop() – 删除栈顶元素 – 时间复杂度:O(1)

执行

在Python中可以通过多种方式实现堆栈。本文介绍了使用Python库中的数据结构和模块实现堆栈。
Python中的 Stack 可以通过以下方式实现:

  • 列表
  • 集合.deque
  • queue.LifoQueue

使用列表实现:

Python 内置的数据结构列表可以作为栈使用。代替 push(),append() 用于将元素添加到堆栈顶部,而 pop() 则以 LIFO 顺序删除元素。
不幸的是,该列表有一些缺点。最大的问题是,随着它的增长,它可能会遇到速度问题。列表中的项目彼此相邻存储在内存中,如果堆栈增长大于当前保存它的内存块,则Python需要进行一些内存分配。这可能导致某些 append() 调用比其他调用花费更长的时间。

Python3
# Python program to
# demonstrate stack implementation
# using list
 
stack = []
 
# append() function to push
# element in the stack
stack.append('a')
stack.append('b')
stack.append('c')
 
print('Initial stack')
print(stack)
 
# pop() function to pop
# element from stack in
# LIFO order
print('\nElements popped from stack:')
print(stack.pop())
print(stack.pop())
print(stack.pop())
 
print('\nStack after elements are popped:')
print(stack)
 
# uncommenting print(stack.pop())
# will cause an IndexError
# as the stack is now empty


Python3
# Python program to
# demonstrate stack implementation
# using collections.deque
 
from collections import deque
 
stack = deque()
 
# append() function to push
# element in the stack
stack.append('a')
stack.append('b')
stack.append('c')
 
print('Initial stack:')
print(stack)
 
# pop() function to pop
# element from stack in
# LIFO order
print('\nElements popped from stack:')
print(stack.pop())
print(stack.pop())
print(stack.pop())
 
print('\nStack after elements are popped:')
print(stack)
 
# uncommenting print(stack.pop())
# will cause an IndexError
# as the stack is now empty


Python3
# Python program to
# demonstrate stack implementation
# using queue module
 
from queue import LifoQueue
 
# Initializing a stack
stack = LifoQueue(maxsize=3)
 
# qsize() show the number of elements
# in the stack
print(stack.qsize())
 
# put() function to push
# element in the stack
stack.put('a')
stack.put('b')
stack.put('c')
 
print("Full: ", stack.full())
print("Size: ", stack.qsize())
 
# get() function to pop
# element from stack in
# LIFO order
print('\nElements popped from the stack')
print(stack.get())
print(stack.get())
print(stack.get())
 
print("\nEmpty: ", stack.empty())


Python3
# Python program to demonstrate
# stack implementation using a linked list.
# node class
 
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
 
 
class Stack:
 
    # Initializing a stack.
    # Use a dummy node, which is
    # easier for handling edge cases.
    def __init__(self):
        self.head = Node("head")
        self.size = 0
 
    # String representation of the stack
    def __str__(self):
        cur = self.head.next
        out = ""
        while cur:
            out += str(cur.value) + "->"
            cur = cur.next
        return out[:-3]
 
    # Get the current size of the stack
    def getSize(self):
        return self.size
 
    # Check if the stack is empty
    def isEmpty(self):
        return self.size == 0
 
    # Get the top item of the stack
    def peek(self):
 
        # Sanitary check to see if we
        # are peeking an empty stack.
        if self.isEmpty():
            raise Exception("Peeking from an empty stack")
        return self.head.next.value
 
    # Push a value into the stack.
    def push(self, value):
        node = Node(value)
        node.next = self.head.next
        self.head.next = node
        self.size += 1
 
    # Remove a value from the stack and return.
    def pop(self):
        if self.isEmpty():
            raise Exception("Popping from an empty stack")
        remove = self.head.next
        self.head.next = self.head.next.next
        self.size -= 1
        return remove.value
 
 
# Driver Code
if __name__ == "__main__":
    stack = Stack()
    for i in range(1, 11):
        stack.push(i)
    print(f"Stack: {stack}")
 
    for _ in range(1, 6):
        remove = stack.pop()
        print(f"Pop: {remove}")
    print(f"Stack: {stack}")


输出:

Initial stack
['a', 'b', 'c']

Elements popped from stack:
c
b
a

Stack after elements are popped:
[]
Traceback (most recent call last):
  File "/home/2426bc32be6a59881fde0eec91247623.py", line 25, in 
    print(stack.pop())  
IndexError: pop from empty list

使用 collections.deque 实现:

Python堆栈可以使用 collections 模块中的 deque 类来实现。在我们需要从容器两端进行更快的追加和弹出操作的情况下,双端队列优于列表,因为与提供 O(n) 的列表相比,双端队列为追加和弹出操作提供了 O(1) 的时间复杂度时间复杂度。
使用了与列表中相同的 deque 方法,append() 和 pop()。

Python3

# Python program to
# demonstrate stack implementation
# using collections.deque
 
from collections import deque
 
stack = deque()
 
# append() function to push
# element in the stack
stack.append('a')
stack.append('b')
stack.append('c')
 
print('Initial stack:')
print(stack)
 
# pop() function to pop
# element from stack in
# LIFO order
print('\nElements popped from stack:')
print(stack.pop())
print(stack.pop())
print(stack.pop())
 
print('\nStack after elements are popped:')
print(stack)
 
# uncommenting print(stack.pop())
# will cause an IndexError
# as the stack is now empty

输出:

Initial stack:
deque(['a', 'b', 'c'])

Elements popped from stack:
c
b
a

Stack after elements are popped:
deque([])
Traceback (most recent call last):
  File "/home/97171a8f6fead6988ea96f86e4b01c32.py", line 29, in 
    print(stack.pop())  
IndexError: pop from an empty deque

使用队列模块实现

Queue 模块也有一个 LIFO Queue,它基本上是一个 Stack。使用 put()函数将数据插入到 Queue 中,而 get() 从 Queue 中取出数据。

此模块中有各种可用的功能:

  • maxsize – 队列中允许的项目数。
  • empty() – 如果队列为空,则返回 True,否则返回 False。
  • full() – 如果队列中有maxsize个项目,则返回 True。如果队列是用 maxsize=0(默认值)初始化的,那么 full() 永远不会返回 True。
  • get() – 从队列中移除并返回一个项目。如果队列为空,请等到有项目可用。
  • get_nowait() – 如果一个项目立即可用,则返回一个项目,否则引发 QueueEmpty。
  • put(item) – 将一个项目放入队列。如果队列已满,请等到有空闲插槽可用后再添加项目。
  • put_nowait(item) – 将一个项目放入队列而不阻塞。
  • qsize() – 返回队列中的项目数。如果没有立即可用的空闲槽,则提高 QueueFull。

Python3

# Python program to
# demonstrate stack implementation
# using queue module
 
from queue import LifoQueue
 
# Initializing a stack
stack = LifoQueue(maxsize=3)
 
# qsize() show the number of elements
# in the stack
print(stack.qsize())
 
# put() function to push
# element in the stack
stack.put('a')
stack.put('b')
stack.put('c')
 
print("Full: ", stack.full())
print("Size: ", stack.qsize())
 
# get() function to pop
# element from stack in
# LIFO order
print('\nElements popped from the stack')
print(stack.get())
print(stack.get())
print(stack.get())
 
print("\nEmpty: ", stack.empty())

输出:

0
Full:  True
Size:  3

Elements popped from the stack
c
b
a

Empty:  True

使用单链表实现:

链表有两个方法 addHead(item) 和 removeHead() 以恒定时间运行。这两种方法都适合实现堆栈。

  • getSize() - 获取堆栈中的项目数。
  • isEmpty() – 如果堆栈为空,则返回 True,否则返回 False。
  • peek() – 返回堆栈中的顶部项目。如果堆栈为空,则引发异常。
  • push(value) – 将一个值压入堆栈的头部。
  • pop() – 移除并返回堆栈头部的值。如果堆栈为空,则引发异常。

下面是上述方法的实现:

Python3

# Python program to demonstrate
# stack implementation using a linked list.
# node class
 
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
 
 
class Stack:
 
    # Initializing a stack.
    # Use a dummy node, which is
    # easier for handling edge cases.
    def __init__(self):
        self.head = Node("head")
        self.size = 0
 
    # String representation of the stack
    def __str__(self):
        cur = self.head.next
        out = ""
        while cur:
            out += str(cur.value) + "->"
            cur = cur.next
        return out[:-3]
 
    # Get the current size of the stack
    def getSize(self):
        return self.size
 
    # Check if the stack is empty
    def isEmpty(self):
        return self.size == 0
 
    # Get the top item of the stack
    def peek(self):
 
        # Sanitary check to see if we
        # are peeking an empty stack.
        if self.isEmpty():
            raise Exception("Peeking from an empty stack")
        return self.head.next.value
 
    # Push a value into the stack.
    def push(self, value):
        node = Node(value)
        node.next = self.head.next
        self.head.next = node
        self.size += 1
 
    # Remove a value from the stack and return.
    def pop(self):
        if self.isEmpty():
            raise Exception("Popping from an empty stack")
        remove = self.head.next
        self.head.next = self.head.next.next
        self.size -= 1
        return remove.value
 
 
# Driver Code
if __name__ == "__main__":
    stack = Stack()
    for i in range(1, 11):
        stack.push(i)
    print(f"Stack: {stack}")
 
    for _ in range(1, 6):
        remove = stack.pop()
        print(f"Pop: {remove}")
    print(f"Stack: {stack}")

输出:

Stack: 10 -> 9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1

Pop: 10
Pop: 9
Pop: 8
Pop: 7
Pop: 6

Stack: 5 -> 4 -> 3 -> 2 -> 1