/ Stack


目录

  1. 链表栈
  2. 数组栈

栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现。

1 链表栈

链表栈是以单链表为基础实现的栈数据结构,主要有以下几个关键点:

  1. 栈顶元素:栈顶元素即为链表的头结点
  2. 压栈:向链表的头结点插进入栈元素,无表头链表则替换插入元素为头结点
  3. 弹栈:弹出链表头结点,并将链表头结点替换为下一个元素
Stack based on linked list:
| item3 |
| | |
| V |
| item2 |
| | |
| V |
| item1 |
-------

完整代码

 class StackEmptyException(Exception): pass

 class StackFullException(Exception): pass

 class Node:
def __init__(self, val=None, nxt=None):
self.value = val
self.next = nxt def __str__(self):
return str(self.value) class Stack:
"""
Stack based on linked list:
| item3 |
| | |
| V |
| item2 |
| | |
| V |
| item1 |
-------
"""
def __init__(self, max=0):
self._top = None
self._max = 0
self.max = max @property
def max(self):
return self._max @max.setter
def max(self, m):
m = int(m)
if m < self.length:
raise Exception('Resize stack failed, please pop some elements first.')
self._max = m
if self._max < 0:
self._max = 0 def init(self, iterable=()):
if not iterable:
return
self._top = Node(iterable[0])
for i in iterable[1:]:
node = self._top
self._top = Node(i)
self._top.next = node def show(self):
def _traversal(self):
node = self._top
while node and node.next:
yield node
node = node.next
yield node
print('\n'.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'\n '+7*'-') @property
def length(self):
if self._top is None:
return 0
node = self._top
i = 1
while node.next:
node = node.next
i += 1
return i @property
def is_empty(self):
return self._top is None @property
def is_full(self):
return bool(self._max and self.length == self._max) def push(self, item):
if self.is_full:
raise StackFullException('Error: trying to push element into a full stack!')
if not self._top:
self._top = Node(item)
return
node = self._top
self._top = Node(item)
self._top.next = node def pop(self):
if self.is_empty:
raise StackEmptyException('Error: trying to pop element from an empty stack!')
node = self._top
self._top = self._top.next
return node.value def top(self):
return self._top.value if self._top else self._top def clear(self):
while self._top:
self.pop() def test(stack):
print('\nShow stack:')
stack.show() print('\nInit linked list:')
stack.init([1, 2, 3, 4, 5])
stack.show() print('\nPush element to stack:')
stack.push(6)
stack.push(7)
stack.push('like')
stack.show() print('\nCheck top element:')
print(stack.top()) print('\nPop element from stack:')
e = stack.pop()
print('Element %s popped,' % e)
stack.show() print('\nSet stack max size:')
try:
stack.max = 1
except Exception as e:
print(e) print('\nSet stack max size:')
stack.max = 7
print(stack.max) print('\nPush full stack:')
try:
stack.push(7)
except StackFullException as e:
print(e) print('\nClear stack:')
stack.clear()
stack.show() print('\nStack is empty:')
print(stack.is_empty) print('\nPop empty stack:')
try:
stack.pop()
except StackEmptyException as e:
print(e) if __name__ == '__main__':
test(Stack())

分段解释
以链表为基础的栈实现,首先需要定义链表结点,以及栈满压栈和栈空弹栈的异常类,

 class StackEmptyException(Exception): pass

 class StackFullException(Exception): pass

 class Node:
def __init__(self, val=None, nxt=None):
self.value = val
self.next = nxt def __str__(self):
return str(self.value)

定义栈类,主要包括两个属性,即栈顶元素和栈大小,

 class Stack:
"""
Stack based on linked list:
| item3 |
| | |
| V |
| item2 |
| | |
| V |
| item1 |
-------
"""
def __init__(self, max=0):
self._top = None
self._max = 0
self.max = max

定义栈最大容量max为属性方法,当设置栈的最大容量值时,若传入的大小小于当前栈大小则提示异常,若传入0或负数大小,则设为无限容量的栈。

     @property
def max(self):
return self._max @max.setter
def max(self, m):
m = int(m)
if m < self.length:
raise Exception('Resize stack failed, please pop some elements first.')
self._max = m
if self._max < 0:
self._max = 0

定义栈的init方法,用于初始化一个可迭代对象为栈结构,接受一个可迭代对象,当空栈时以第一个元素为栈顶,随后依次压栈,最后入栈的元素为栈顶元素。

     def init(self, iterable=()):
if not iterable:
return
self._top = Node(iterable[0])
for i in iterable[1:]:
node = self._top
self._top = Node(i)
self._top.next = node

定义栈的show方法,用于显示栈,首先遍历栈元素,然后依照格式化输出,当空栈时则栈顶/底元素为None。

     def show(self):
def _traversal(self):
node = self._top
while node and node.next:
yield node
node = node.next
yield node
print('\n'.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'\n '+7*'-')

定义栈的length属性方法,用于返回当前栈内元素数量,通过链表遍历计数实现(类似获取链表长度)。

     @property
def length(self):
if self._top is None:
return 0
node = self._top
i = 1
while node.next:
node = node.next
i += 1
return i

定义栈的is_empty属性方法,用于判断栈是否为空栈。

     @property
def is_empty(self):
return self._top is None

定义栈的is_full属性方法,用于判断栈容量是否已满。

     @property
def is_full(self):
return bool(self._max and self.length == self._max)

定义栈的push方法,用于实现压栈过程,即向栈链前端插入入栈元素,栈满压栈则提示异常。

     def push(self, item):
if self.is_full:
raise StackFullException('Error: trying to push element into a full stack!')
if not self._top:
self._top = Node(item)
return
node = self._top
self._top = Node(item)
self._top.next = node

定义栈的pop方法,用于实现弹栈过程,弹出栈顶元素并替换栈顶元素为下一个元素,栈空弹栈则提示异常。

     def pop(self):
if self.is_empty:
raise StackEmptyException('Error: trying to pop element from an empty stack!')
node = self._top
self._top = self._top.next
return node.value

定义栈的top方法,用于获取栈顶元素,当栈顶元素为None时,返回None。

     def top(self):
return self._top.value if self._top else self._top

定义栈的clear方法,用于清空栈,即依次弹栈至空栈。

     def clear(self):
while self._top:
self.pop()

最后定义一个测试函数,用于对栈类进行操作测试。

首先实例化一个栈,并将一个列表元素依次压入栈中,最后显示栈元素

 def test(stack):
print('\nShow stack:')
stack.show() print('\nInit linked list:')
stack.init([1, 2, 3, 4, 5])
stack.show()

得到结果

 Show stack:
| None |
------- Init linked list:
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
-------

执行压栈操作,将元素压入栈中,

     print('\nPush element to stack:')
stack.push(6)
stack.push(7)
stack.push('like')
stack.show()

得到结果

Push element to stack:
| like |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
-------

检测栈顶元素并弹出栈顶元素

     print('\nCheck top element:')
print(stack.top()) print('\nPop element from stack:')
e = stack.pop()
print('Element %s popped,' % e)
stack.show()

得到结果

Check top element:
like Pop element from stack:
Element like popped,
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
-------

尝试修改栈的最大容量,当修改容量小于当前栈内元素数量时,将会触发异常

     print('\nSet stack max size:')
try:
stack.max = 1
except Exception as e:
print(e) print('\nSet stack max size:')
stack.max = 7
print(stack.max)

得到结果

Set stack max size:
Resize stack failed, please pop some elements first. Set stack max size:
7

尝试对一个满元素栈进行压栈操作,将引发异常

     print('\nPush full stack:')
try:
stack.push(7)
except StackFullException as e:
print(e)

得到结果

Push full stack:
Error: trying to push element into a full stack!

随后清空栈,并检查栈是否为空,最后尝试对空栈进行弹栈操作,同样会引发一个异常

     print('\nClear stack:')
stack.clear()
stack.show() print('\nStack is empty:')
print(stack.is_empty) print('\nPop empty stack:')
try:
stack.pop()
except StackEmptyException as e:
print(e)

得到结果

Clear stack:
| None |
------- Stack is empty:
True Pop empty stack:
Error: trying to pop element from an empty stack!

2 数组栈

数组栈是栈的另一种实现方式,在C语言中以数组的形式实现,而在Python中,则可以使用与数组类似的列表进行实现。

Stack based on array/list:
| 4 |
| 3 |
| 2 |
| 1 |
-------

数组栈中需要实现的方法接口与链表栈相同。只是在数据存储时由链表变成了数组/列表。由于Python的列表本身即是一种很方便的线性结构,因此数组栈的实现十分简单。

完整代码

 from linked_list_stack import StackEmptyException, StackFullException, test

 class Stack:
"""
Stack based on array/list:
| 4 |
| 3 |
| 2 |
| 1 |
-------
"""
def __init__(self, max=0):
self._array = []
self._max = 0
self.max = max @property
def max(self):
return self._max @max.setter
def max(self, m):
m = int(m)
if m < self.length:
raise Exception('Resize stack failed, please pop some elements first.')
self._max = m
if self._max < 0:
self._max = 0 def init(self, iterable=()):
if not iterable:
return
for i in iterable:
self._array.append(i) def show(self):
def _traversal(self):
if not self._array:
return [None]
return self._array[::-1]
print('\n'.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'\n '+7*'-') @property
def length(self):
return len(self._array) @property
def is_empty(self):
return self._array == [] @property
def is_full(self):
return bool(self._max and self.length == self._max) def push(self, item):
if self.is_full:
raise StackFullException('Error: trying to push element into a full stack!')
self._array.append(item) def pop(self):
if self.is_empty:
raise StackEmptyException('Error: trying to pop element from an empty stack!')
return self._array.pop() def top(self):
return self._array[-1] def clear(self):
# self._array = []
while self._array:
self.pop() if __name__ == '__main__':
test(Stack())

分段解释

首先从链表栈中导入两个异常类和测试函数,

 from linked_list_stack import StackEmptyException, StackFullException, test

然后定义栈类,与链表栈不同的地方在于,存储数据的方式换成了列表

 class Stack:
"""
Stack based on array/list:
| 4 |
| 3 |
| 2 |
| 1 |
-------
"""
def __init__(self, max=0):
self._array = []
self._max = 0
self.max = max

与前面的链表栈一样,定义栈的容量。

     @property
def max(self):
return self._max @max.setter
def max(self, m):
m = int(m)
if m < self.length:
raise Exception('Resize stack failed, please pop some elements first.')
self._max = m
if self._max < 0:
self._max = 0

定义栈的init方法,添加入栈元素时只需要在列表末尾加入元素即可,

     def init(self, iterable=()):
if not iterable:
return
for i in iterable:
self._array.append(i)

下面的几个方法与链表栈类似,只是操作时换成了对数组列表的检测,

     def show(self):
def _traversal(self):
if not self._array:
return [None]
return self._array[::-1]
print('\n'.join(map(lambda x: '|{:^7}|'.format(str(x)), _traversal(self)))+'\n '+7*'-') @property
def length(self):
return len(self._array) @property
def is_empty(self):
return self._array == [] @property
def is_full(self):
return bool(self._max and self.length == self._max)

定义栈的push方法,实现压栈操作,压栈只需要对列表进行append即可,

     def push(self, item):
if self.is_full:
raise StackFullException('Error: trying to push element into a full stack!')
self._array.append(item)

定义栈的pop方法,实现弹栈操作,弹栈只需要对列表进行pop即可,

     def pop(self):
if self.is_empty:
raise StackEmptyException('Error: trying to pop element from an empty stack!')
return self._array.pop()

定义栈的top方法,实现栈顶元素获取,返回列表最后一位元素即可,

     def top(self):
return self._array[-1]

定义栈的clear方法,实现栈的清空操作,可以直接清空数组列表或依次将栈内元素弹出栈,

     def clear(self):
# self._array = []
while self._array:
self.pop()

最后,利用测试函数对数组栈进行测试

 if __name__ == '__main__':
test(Stack())

得到结果与链表栈相同

Show stack:
| None |
------- Init linked list:
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
------- Push element to stack:
| like |
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
------- Check top element:
like Pop element from stack:
Element like popped,
| 7 |
| 6 |
| 5 |
| 4 |
| 3 |
| 2 |
| 1 |
------- Set stack max size:
Resize stack failed, please pop some elements first. Set stack max size:
7 Push full stack:
Error: trying to push element into a full stack! Clear stack:
| None |
------- Stack is empty:
True Pop empty stack:
Error: trying to pop element from an empty stack!

相关阅读


1. 单链表

Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现的更多相关文章

  1. Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现

    队列 / Queue 数组队列 数组队列是队列基于数组的一种实现,其实现类似于数组栈,是一种FIFO的线性数据结构. Queue: <--| 1 | 2 | 3 | 4 | 5 |<-- ...

  2. Python与数据结构[4] -> 散列表[0] -> 散列表与散列函数的 Python 实现

    散列表 / Hash Table 散列表与散列函数 散列表是一种将关键字映射到特定数组位置的一种数据结构,而将关键字映射到0至TableSize-1过程的函数,即为散列函数. Hash Table: ...

  3. Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现

    二叉树 / Binary Tree 二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点. Binary Tree: 00 |_____ | | 00 00 |__ |__ | | | | ...

  4. Python与数据结构[3] -> 树/Tree[1] -> 表达式树和查找树的 Python 实现

    表达式树和查找树的 Python 实现 目录 二叉表达式树 二叉查找树 1 二叉表达式树 表达式树是二叉树的一种应用,其树叶是常数或变量,而节点为操作符,构建表达式树的过程与后缀表达式的计算类似,只不 ...

  5. Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现

    AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...

  6. C栈stack

    栈是一种  特殊的线性表 栈仅能在线性表的一端进行操作 栈顶(Top):允许操作的一端 栈底(Bottom):不允许操作的一端 Stack的常用操作 创建栈 销毁栈 清空栈 进栈 出栈 获取栈顶元素 ...

  7. (python数据分析)第03章 Python的数据结构、函数和文件

    本章讨论Python的内置功能,这些功能本书会用到很多.虽然扩展库,比如pandas和Numpy,使处理大数据集很方便,但它们是和Python的内置数据处理工具一同使用的. 我们会从Python最基础 ...

  8. Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET

    Python -- 堆数据结构 heapq - I love this game! - 博客频道 - CSDN.NET Python -- 堆数据结构 heapq 分类: Python 2012-09 ...

  9. [Python] 数据结构--实现顺序表、链表、栈和队列

    说明: 本文主要展示Python实现的几种常用数据结构:顺序表.链表.栈和队列. 附有实现代码. 来源主要参考网络文章. 一.顺序表 1.顺序表的结构 一个顺序表的完整信息包括两部分,一部分是表中元素 ...

随机推荐

  1. shell脚本批量下载资源并保留路径

    示例资源列表 如url.txt: http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png http://su.bdimg.co ...

  2. NOIP2018 集训(一)

    A题 Simple 时间限制:1000ms | 空间限制:256MB 问题描述 对于给定正整数\(n,m\),我们称正整数\(c\)为好的,当且仅当存在非负整数\(x,y\)使得\(n×x+m×y=c ...

  3. Entity Framework(三)---FluentAPI和增删查改

    一.FluentAPI: 1.基本配置: namespace ConsoleApp14.ModelConfig { public class PersonConfig: EntityTypeConfi ...

  4. python学习总结---面向对象2

    面向对象三大特点 - 封装:既是对数据结构的封装,有是处理数据的方法的封装. - 继承:强调的父子类的关系. - 多态:不同对象调用相同的方法,有不同的响应. 类的继承 - 相关概念 - 继承:父类的 ...

  5. DataSource的设置

    1.Centos和redhat,Fedora等版本无须设置,直接在cloud.cfg指定,默认是EC2 datasource_list: ['ConfigDrive','OpenStack'] 2.u ...

  6. Python编码报错

    Python默认编码错误SyntaxError: Non-ASCII character '\xe5'之解决方法在编写Python时,当使用中文输出或注释时运行脚本,会提示错误信息:SyntaxErr ...

  7. Mysql 查询—按位运算

    前言:虽说这是件小事儿,但本宝宝思前想后,还是为它留下一笔,嘿嘿.反正写博客不浪费纸和笔!好久没有开启我的逗比模式了,我亲爱的乖徒弟DBA,DBB,DBAA等,好久不见你们,遥祝幸福快乐+DB. 整个 ...

  8. 膜拜膜拜c++

    被一个virtual搞得脑袋疼了好几天,明天继续虚函数+虚继承混合,伤不起,伤不起

  9. 201621123034 《Java程序设计》第8周学习总结

    作业08-集合 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 答 ...

  10. 清除浮动float (:after方法)

    1. 什么时候需要清除浮动?清除浮动有哪些方法? (1)对元素进行了浮动(float)后,该元素就会脱离文档流,浮动在文档之上.在CSS中,任何元素都可以浮动.浮动元素会生成一个块级框,而不论它本身是 ...