189 lines
6.4 KiB
Markdown
189 lines
6.4 KiB
Markdown
# 在 Python 中实现堆栈
|
||
|
||
> 原文:<https://www.pythonforbeginners.com/data-types/implement-stack-in-python>
|
||
|
||
栈是一种数据结构,它遵循后进先出(LIFO)的顺序来访问元素。在堆栈中,我们只能访问最近添加的元素。堆栈在表达式处理、回溯和函数调用等应用中有很多用途。在本文中,我们将尝试用 python 实现带链表的堆栈数据结构。
|
||
|
||
## 使用链表在 Python 中实现堆栈
|
||
|
||
链表是一种线性数据结构,其中每个数据对象指向另一个对象。为了用链表实现一个堆栈,我们将不得不执行插入和删除,以及从链表中删除元素,这样它将花费恒定的时间。只有当我们在链表的开头插入和删除元素时,这才是可能的。
|
||
|
||
为了在 python 中实现带链表的堆栈,我们将首先定义一个 node 对象,它将包含当前元素,并使用引用 next 指向插入它之前的节点。在 python 中,该节点可以按如下方式实现。
|
||
|
||
```py
|
||
class Node:
|
||
def __init__(self,data,size):
|
||
self.data=data
|
||
self.next=None
|
||
```
|
||
|
||
当我们用链表实现一个堆栈时,它将有一个名为 top 的元素,这个元素将引用链表中最近插入的元素。所有其他元素都可以通过它来访问。我们可以用 python 实现一个空栈,top 初始化为 None,stackSize 初始化为 0,如下所示。
|
||
|
||
```py
|
||
class Stack:
|
||
def __init__(self):
|
||
self.top=None
|
||
self.stackSize=0
|
||
```
|
||
|
||
## 在 Python 中实现栈中的推送操作
|
||
|
||
当我们将一个元素插入到堆栈中时,这个操作叫做 push 操作。为了在链表的帮助下实现栈中的 push 操作,对于每一次插入,我们将在链表的开头添加要插入的元素。这样,最近的元素将总是在链表的开始。然后,我们将堆栈的顶部元素指向链表的开头,并将 stackSize 递增 1。可以使用 python 中的链表实现推送操作,如下所示。
|
||
|
||
```py
|
||
def push(self,data):
|
||
temp=Node(data)
|
||
if self.top is None:
|
||
self.top=temp
|
||
self.stackSize= self.stackSize+1
|
||
else:
|
||
temp.next=self.top
|
||
self.top=temp
|
||
self.stackSize=self.stackSize+1
|
||
```
|
||
|
||
## 用 Python 实现堆栈中的弹出操作
|
||
|
||
当我们从堆栈中取出一个元素时,这个操作被称为弹出操作。要从堆栈中取出的元素是最近添加到堆栈中的元素。正如我们所知,在推送操作中,我们将最近的元素添加到堆栈顶部指向的链表的开头,因此我们将删除顶部指向的元素,并将顶部指向下一个最近的元素。在执行弹出操作之前,我们将检查堆栈是否为空。如果堆栈为空,即 top 指向 None,我们将使用 [python try except](https://www.pythonforbeginners.com/error-handling/python-try-and-except) 引发一个异常,并显示堆栈为空的消息。我们可以如下实现 pop 操作。
|
||
|
||
```py
|
||
def pop(self):
|
||
try:
|
||
if self.top == None:
|
||
raise Exception("Stack is Empty")
|
||
else:
|
||
temp=self.top
|
||
self.top=self.top.next
|
||
tempdata=temp.data
|
||
self.stackSize= self.stackSize-1
|
||
del temp
|
||
return tempdata
|
||
except Exception as e:
|
||
print(str(e))
|
||
```
|
||
|
||
## 如何访问栈顶元素
|
||
|
||
由于栈顶的元素被 top 引用,我们只需返回 top 指向的节点中的数据。它可以按如下方式实现。
|
||
|
||
```py
|
||
def top_element(self):
|
||
try:
|
||
if self.top == None:
|
||
raise Exception("Stack is Empty")
|
||
else:
|
||
return self.top.data
|
||
except Exception as e:
|
||
print(str(e))
|
||
```
|
||
|
||
## 获取堆栈的大小
|
||
|
||
因为我们在 stackSize 变量中保留了当前的堆栈大小,所以我们只需返回 stackSize 变量 top 中的值。这可以如下进行。
|
||
|
||
```py
|
||
def size(self):
|
||
return self.stackSize
|
||
```
|
||
|
||
## 检查堆栈是否为空
|
||
|
||
元素 top 指的是堆栈中最近的元素。如果堆栈中没有元素,top 将指向 None。因此,要检查堆栈是否为空,我们只需检查 top 是否指向 None 或者 stackSize 变量的值是否为 0。我们可以实现 isEmpty()方法来检查堆栈是否为空,如下所示。
|
||
|
||
```py
|
||
def isEmpty(self):
|
||
if self.stackSize==0:
|
||
return True
|
||
else:
|
||
return False
|
||
```
|
||
|
||
使用 python 中的链表实现堆栈的完整工作代码如下。
|
||
|
||
```py
|
||
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Created on Sun Apr 25 00:28:19 2021
|
||
|
||
@author: aditya1117
|
||
"""
|
||
|
||
class Node:
|
||
def __init__(self,data):
|
||
self.data=data
|
||
self.next=None
|
||
class Stack:
|
||
def __init__(self):
|
||
self.top=None
|
||
self.stackSize=0
|
||
def push(self,data):
|
||
temp=Node(data)
|
||
if self.top is None:
|
||
self.top=temp
|
||
self.stackSize= self.stackSize+1
|
||
else:
|
||
temp.next=self.top
|
||
self.top=temp
|
||
self.stackSize=self.stackSize+1
|
||
def pop(self):
|
||
try:
|
||
if self.top == None:
|
||
raise Exception("Stack is Empty")
|
||
else:
|
||
temp=self.top
|
||
self.top=self.top.next
|
||
tempdata=temp.data
|
||
self.stackSize= self.stackSize-1
|
||
del temp
|
||
return tempdata
|
||
except Exception as e:
|
||
print(str(e))
|
||
def isEmpty(self):
|
||
if self.stackSize==0:
|
||
return True
|
||
else:
|
||
return False
|
||
def size(self):
|
||
return self.stackSize
|
||
def top_element(self):
|
||
try:
|
||
if self.top == None:
|
||
raise Exception("Stack is Empty")
|
||
else:
|
||
return self.top.data
|
||
except Exception as e:
|
||
print(str(e))
|
||
s=Stack()
|
||
s.push(1)
|
||
print(s.size())
|
||
|
||
s.push(2)
|
||
print(s.size())
|
||
|
||
print(s.pop())
|
||
print(s.size())
|
||
print(s.pop())
|
||
print(s.stackSize)
|
||
|
||
print(s.top_element())
|
||
print(s.isEmpty())
|
||
```
|
||
|
||
输出:
|
||
|
||
```py
|
||
1
|
||
2
|
||
2
|
||
1
|
||
1
|
||
0
|
||
Stack is Empty
|
||
None
|
||
True
|
||
```
|
||
|
||
## 结论
|
||
|
||
在本文中,我们使用 python 中的链表实现了 stack 及其所有操作。为了更深入地了解它,并理解 stack 与内置数据结构(如 [python dictionary](https://www.pythonforbeginners.com/dictionary/how-to-use-dictionaries-in-python/) 、list 和 set)有何不同,复制上面示例中给出的完整代码,并试验其中的操作。请继续关注更多内容丰富的文章。 |