📅  最后修改于: 2020-10-29 01:21:49             🧑  作者: Mango
在本教程中,我们将学习堆栈的基础知识并使用Python代码实现它。
堆栈是一种线性数据结构,其中数据按对象排列在另一个堆栈上。它以LIFO(后进先出)的方式存储数据。数据的存储顺序与板在厨房中一个接一个地排列一样。堆栈的简单示例是编辑器中的“撤消”功能。撤消功能适用于我们完成的最后一个事件。
我们总是从盘子堆中挑选最后一块盘子。在堆栈中,新元素插入到一端,而一个元素只能移到该端。
我们可以在堆栈中执行两个操作-PUSH和POP。 PUSH操作是在添加元素时,POP操作是在从堆栈中删除元素时。
Python提供了以下堆栈常用的方法。
Python提供了多种实现堆栈的方法。在本节中,我们将讨论使用Python及其模块的堆栈实现。
我们可以通过以下方式在Python中实现堆栈。
Python列表可用作堆栈。它使用append()方法将元素插入到列表中,其中堆栈使用push()方法。该列表还提供了pop()方法来删除最后一个元素,但是列表中存在一些缺点。列表随着增长而变慢。
该列表将新元素存储在另一个元素中。如果列表增加且内存不足,则Python分配一些内存。这就是为什么列表变慢的原因。让我们了解以下示例-
# initial empty stack
my_stack = []
# append() function to push
# element in the my_stack
my_stack.append('x')
my_stack.append('y')
my_stack.append('z')
print(my_stack)
# pop() function to pop
# element from my_stack in
# LIFO order
print('\nElements poped from my_stack:')
print(my_stack.pop())
print(my_stack.pop())
print(my_stack.pop())
print('\nmy_stack after elements are poped:')
print(my_stack)
输出:
['x', 'y', 'z']
Elements poped from my_stack:
z
y
x
my_stack after elements are poped:
[]
Traceback (most recent call last):
File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/Stack.py", line 21, in
print(my_stack.pop())
IndexError: pop from empty list
说明-
在上面的代码中,我们定义了一个空列表。我们使用append()方法一一插入了元素。这类似于push()方法。我们还使用pop()方法删除了元素。 pop()方法返回列表的最后一个元素。
收集模块提供了双端队列类,该类用于创建Python堆栈。双端队列发音为“ deck”,意思是“双端队列”。由于双端队列比列表更快速地执行附加和弹出操作,因此可以优先于列表。时间复杂度为O(1),其中列表取O(n)。
让我们了解以下示例-
例
from collections import deque
my_stack = deque()
# append() function is used to push
# element in the my_stack
my_stack.append('a')
my_stack.append('b')
my_stack.append('c')
print('Initial my_stack:')
print(my_stack)
# pop() function is used to pop
# element from my_stack in
# LIFO order
print('\nElements poped from my_stack:')
print(my_stack.pop())
print(my_stack.pop())
print(my_stack.pop())
print('\nmy_stack after elements are poped:')
print(my_stack)
输出:
Initial my_stack:
deque(['a', 'b', 'c'])
Elements poped from my_stack:
c
b
a
my_stack after elements are poped:
deque([])
说明:
上面的代码几乎与前面的示例相似。但是,唯一的区别是,我们已从收集模块中导入了双端队列。
该列表将元素紧挨着存储,并使用连续的内存。这对于几种操作(例如索引到列表)最有效。例如-由于Python知道特定元素的确切位置,因此获取list1 [2]很快。连续的内存还允许切片在列表上正常工作。
该列表比另一些对象花费更多的时间来append()一些对象。如果连续内存块已满,它将获得另一个块,该块可能比正常的append()函数花费更长的时间。
队列模块具有LIFO队列,该队列与堆栈相同。通常,队列使用put()方法添加数据,并使用()方法获取数据。
以下是队列中可用的一些方法。
让我们了解以下队列模块示例。
范例-
# Implementing stack using the queue module
from queue import LifoQueue
# Initializing a my_stack stack with maxsize
my_stack = LifoQueue(maxsize = 5)
# qsize() display the number of elements
# in the my_stack
print(my_stack.qsize())
# put() function is used to push
# element in the my_stack
my_stack.put('x')
my_stack.put('y')
my_stack.put('z')
print("Stack is Full: ", my_stack.full())
print("Size of Stack: ", my_stack.qsize())
# To pop the element we used get() function
# from my_stack in
# LIFO order
print('\nElements poped from the my_stack')
print(my_stack.get())
print(my_stack.get())
print(my_stack.get())
print("\nStack is Empty: ", my_stack.empty())
输出:
0
Stack is Full: False
Size of Stack: 3
Elements poped from the my_stack
z
y
x
Stack is Empty: True
说明-
在上面,我们导入了队列模块LIFOqueue。它的工作原理与堆栈相同,但是此模块包括上述一些其他功能。我们使用maxsize定义了一个堆栈,这意味着它最多可以容纳五个值。
初始数组大小为零;我们使用put()方法将三个元素压入堆栈。现在,我们再次检查堆栈是否为空以及堆栈的大小。我们有三个元素。我们使用get()方法弹出元素。它首先删除最后添加的元素。删除所有元素后,我们得到一个空堆栈。
我们还可以在多线程程序中使用Python堆栈。这是一个高级主题,但不经常使用,因此,如果您对线程不感兴趣,可以跳过本节。
如果我们在程序中使用线程,则列表和双端队列的行为会有所不同。在多线程编程中使用列表可能很危险,因为它不是线程安全的。
另一方面,双端队列有点复杂,因为它的append()和pop()方法是原子的,这意味着它们不会被其他线程中断。
我们可以使用双端队列来构建多线程程序,但是将来可能不会引起什么复杂性。
现在出现了一个问题,我们如何构建带有线程的Python堆栈程序。
答案是,我们可以使用LIFOqueue,并且知道LIFO代表什么-后进先出。它使用put()和gets()添加和删除堆栈元素。
我们提到了在Python中实现堆栈的三种方法。上述方法具有其自身的优点或缺点。
让我们消除混乱;我们在堆栈中使用线程,您应该使用Lifoqueue,但要确保其弹出和推送元素的性能。但是,如果您不使用线程,请使用双端队列。
我们还可以使用列表来实现堆栈,但是列表可能存在潜在的内存重新分配问题。列表和双端队列在界面上是相同的,但是双端队列没有内存分配问题。
我们已经简要定义了一个堆栈及其实现。 Python堆栈可用于现实程序中。我们可以根据自己的要求选择实施方法。我们还定义了带有线程环境的Python堆栈。