Python数据结构学习笔记——栈
目录
- 一、栈的定义和特性
- (一)栈的定义
- (二)栈的反转特性
- 二、实现分析步骤
- 三、栈的Python实现代码
- 四、栈的应用
- (一)匹配圆括号
- (二)匹配符号
- (三)模2除法(十进制转二进制)
- (四)进制转换
- 结语
一、栈的定义和特性
(一)栈的定义
栈是一种线性数据结构,栈是元素的有序集合,其元素的顺序取决于添加顺序或移除顺序,它有两端,称作顶端和底端,即对应栈的栈顶
和栈底
,栈中元素的添加称为入栈
,而元素的移除称为出栈
,栈中元素的添加操作和移除操作都发生在其顶端
。
栈中最后添加的元素将最先被移除,栈的排序原则被称作LIFO,即后进先出
,最先添加的元素在栈底,它最后最移出。
简单来说,可比喻为几本书或砖头叠在一起,需要依次从上至下一本一本地拿出书,最下面的那本书最后被拿出。
(二)栈的反转特性
栈的反转特性最明显的例子体现在浏览器的返回键中,我们知道在浏览网页时,实际上的网页是文件,是由 HTML 构成的文件,每个网页文件都有一个唯一的URL(即统一资源定位符)。
当从当前网页跳转到另一个网页页面时,当前浏览的网页处于栈顶,而之前的网页相对当前网页位于栈底,也就是这些网页的URL都被存放在一个栈中。
二、实现分析步骤
通过Python中的类与对象,在类中定义几个方法,且使用列表来实现栈的相关操作,栈的操作有:
1、创建一个空栈
,通过构造方法创建一个空列表;
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈
2、向栈(栈顶)中添加元素
,通过列表的append()或insert()实现添加新的元素至栈中。(若将列表的尾部作为栈的顶端,则通过append()实现;而若将列表的头部作为栈的顶端,则通过insert()实现,insert()第一个参数表示索引位置,第二个参数即要添加的元素,由于是向栈顶添加元素,则第一个参数为0(列表的下标从0开始));
def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值【self.items.insert(0,item)】
3、删除栈顶元素
,通过列表的pop()实现删除栈顶的元素。(若将列表的尾部作为栈的顶端,pop()内无参数,即此时删除列表的末尾元素,也就是栈的顶端元素;而若将列表的头部作为栈的顶端,则pop(0)表示移除列表中下标为0的元素);
def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容【return self.items.pop(0)】
4、返回栈顶元素
,若将列表的尾部作为栈的顶端,则通过len()先取得列表的长度,由于下标是从0开始,所以要减1;而若将列表的头部作为栈的顶端,则直接通过索引列表下标为0的元素);
def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容【return self.items[0]】
5、检查栈是否为空
,通过比较运算符“==”比较栈是否为空,若为空,则返回布尔值False,若不为空,则返回True;
def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值
6、返回栈中元素数目
,通过len()取列表的长度,即返回栈中元素的数目。
def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数
三、栈的Python实现代码
将列表的尾部作为栈的顶端:
# 通过列表实现栈的操作(以列表尾部作为栈的顶端)
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数s = Stack() # s是一个新创建的空栈,创建一个对象,即对象名称=类名称()
print(s.isEmpty()) # 检查栈是否为空
s.push("wddd")
s.push("w")
s.push(123)
print(s.peek()) # 返回栈最顶端的元素
print(s.size()) # 返回当前栈中的元素数目
s.push(False)
print(s.size())
print(s.isEmpty())
s.push(0.2)
print(s.pop()) # 删除栈顶元素
print(s.peek())
print(s.size())
运行结果如下:
四、栈的应用
(一)匹配圆括号
我们知道圆括号由左括号“(”和右括号“)”进行匹配的,通过创建一个空栈来保存括号,从左至右依次处理括号,若匹配到左括号则通过push()方法将其添加至栈中,而若匹配到右括号则通过pop()方法删除栈顶元素,最后若所有括号都匹配则栈为空,程序会返回一个布尔值来表示括号是否匹配。
程序完整代码及解析如下:
# 通过列表实现栈的操作(以列表尾部作为栈的顶端)
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数# 定义一个有参函数Par_Checker(),其参数parenthesis是输入的括号
def Par_Checker(parenthesis):s = Stack() # s是一个新创建的空栈,创建一个对象balanced = Trueindex = 0while index < len(parenthesis) and balanced: # 若当前索引值小于输入的括号的总长度且变量balanced的值为正确时,一直执行while循环下去symbol = parenthesis[index]# 取输入的括号赋给变量symbol,变量index的初值为0if symbol == "(": # 若匹配到左括号则通过push()方法将其添加至栈中s.push(symbol)else:if s.isEmpty(): # 检查栈是否为空,它不需要参数,会返回一个布尔值balanced = False # 栈为空,变量balanced的值变为Falseelse:s.pop() # 若匹配到右括号则通过pop()方法删除栈顶元素index = index + 1 # 索引加一,对下一个括号进行检查if balanced and s.isEmpty(): # 如果栈为空,则代表所有括号都匹配成功return Trueelse:return False#测试
print(Par_Checker("(()(("))
print(Par_Checker(")(("))
print(Par_Checker("(()(()))"))
运行结果如下:
(二)匹配符号
通过改进匹配圆括号的程序从而实现对符号“()”、“[]”和“{}”的匹配,在原有的基础上加了一个函数matches(),该函数检查每一个从栈顶移除的符合是否与当前的右符合相匹配,匹配符号的程序完整代码及解析如下:
# 通过列表实现栈的操作(以列表尾部作为栈的顶端)
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数# 定义一个有参函数matches(),该函数检查每一个从栈顶移除的符合是否与当前的右符合相匹配
def matches(left, right):left = "([{"right = ")]}"return left.index(left) == right.index(right) # index()用于检查子字符串是否在字符串中# 定义一个有参函数Par_Checker(),其参数parenthesis是输入的括号
def Par_Checker(parenthesis):s = Stack() # s是一个新创建的空栈,创建一个对象balanced = Trueindex = 0while index < len(parenthesis) and balanced: # 若当前索引值小于输入的符号的总长度且变量balanced的值为正确时,一直执行while循环下去symbol = parenthesis[index] # 取输入的符号赋给变量symbol,变量index的初值为0if symbol in "([{": # 若匹配到左符号则通过push()方法将其添加至栈中s.push(symbol)else:if s.isEmpty(): # 检查栈是否为空,它不需要参数,会返回一个布尔值balanced = False # 栈为空,变量balanced的值变为Falseelse:top = s.pop() # 若匹配到右符号则通过pop()方法删除栈顶元素if not matches(top, symbol): # 调用matches()函数检查每一个从栈顶移除的符合是否与当前的右符合相匹配,即若未匹配执行以下语句balanced = Falseindex = index + 1 # 索引加一,对下一个符号进行检查if balanced and s.isEmpty(): # 如果栈为空,则代表所有符号都匹配成功return Trueelse:return False#测试
print(Par_Checker("(({)("))
print(Par_Checker("]("))
print(Par_Checker("{([]})"))
运行结果如下:
(三)模2除法(十进制转二进制)
我们知道将十进制转二进制可以通过模2除法的方法实现,也就是除2取余,逆序排列,如下十进制25转换为二进制:
最后可得25=0001 1001=11001:
我们从步骤上可以看出,计算出的第一个余数是得到结果的最后一位,而最后计算出的余数是结果的第一位,所以可以将得到的二进制数看成一系列数字,创建一个空栈,通过一系列方法得到二进制数字。
模2除法的程序完整代码及解析如下:
# 通过列表实现栈的操作(以列表尾部作为栈的顶端)
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数# 创建一个有参函数DivideBy2(),参数为一个十进制数
def DivideBy2(decNumber):s = Stack() # s是一个新创建的空栈,创建一个对象while decNumber > 0: # 若输入的十进制大于0,则执行while循环一直下去rem = decNumber % 2 # 参数rem为余数,即十进制数每次除2得到的余数s.push(rem) # 通过push()方法将得到的余数添加到栈的顶端decNumber = decNumber // 2 # 输入的十进制整数除2,即十进制与2的整数商binString = "" # 定义一个空字符串binString用于存放二进制数字while not s.isEmpty(): # 若栈不为空,则执行while循环一直下去binString = binString + str(s.pop()) # 通过pop()方法将栈顶的元素移除,通过str()转换为字符串类型并通过"+"拼接赋值给字符串binStringreturn binString # 得到的二进制值print(DivideBy2(17))
print(DivideBy2(255))
print(DivideBy2(1024))
print(DivideBy2(2022))
运行结果如下:
(四)进制转换
根据十进制转二进制的程序代码可以进一步改进,首先该函数可以另外定义一个参数base,它表示相应的进制数(二进制、八进制、十六进制),另外创建一个字符串digits,由于有十进制转十六进制,所以该字符串的内容应该有ABCDEF,再加上数字0-9,即该字符串的内容为“0123456789ABCDEF”,它用于存储对应位置上的数字,当从栈中移除一个十进制余相应的进制数得到的余数时,就可以作为访问数字的下标,即对应的数字会被添加到结果中,最后再通过pop()方法将栈顶的元素移除,通过对字符串索引的方式依次索引移除的元素,并通过"+"拼接赋值给字符串newString。
十进制转其他进制(二进制、八进制、十六进制)的程序完整代码及解析如下:
# 通过列表实现栈的操作(以列表尾部作为栈的顶端)
class Stack:def __init__(self):self.items = [] # 创建一个空栈,它不需要参数,且会返回一个空栈def isEmpty(self):return self.items == [] # 检查栈是否为空,它不需要参数,且会返回一个布尔值def push(self, item):self.items.append(item) # 将一个元素添加到栈的顶端,它需要一个参数item,且无返回值def pop(self):return self.items.pop() # 将栈顶的元素移除,它不需要参数,但会返回顶端的元素,且修改栈的内容def peek(self):return self.items[len(self.items) - 1] # 返回栈顶端的元素,它不需要参数,不会修改栈的内容def size(self):return len(self.items) # 返回栈中元素的数目,它不需要参数,且会返回一个整数# 创建一个有参函数BaseConverter(),参数为进制数和进制
def BaseConverter(decNumber, base):digits = "0123456789ABCDEF" # 创建一个字符串digits,存储对应位置上的数字,当从栈中移除一个余数时,它可以被用作访问数字的下标,对应的数字会被添加到结果中s = Stack()while decNumber > 0: # 若输入的进制数大于0,则执行while循环一直下去rem = decNumber % base # 参数rem为余数,即进制数每次除相应的进制得到的余数s.push(rem) # 通过push()方法将得到的余数添加到栈的顶端decNumber = decNumber // base # 输入的进制数整数除相应的进制newString = "" # 定义一个空字符串newString用于存放二进制数字while not s.isEmpty(): # 若栈不为空,则执行while循环一直下去newString = newString + digits[s.pop()] # 通过pop()方法将栈顶的元素移除,通过对字符串索引的方式依次索引移除的元素,并通过"+"拼接赋值给字符串newStringreturn newString # 得到的相应进制值#测试
print(BaseConverter(17, 2))
print(BaseConverter(255, 8))
print(BaseConverter(1024, 16))
print(BaseConverter(2022, 16))
运行结果如下:
结语
参考书籍:《Python数据结构与算法分析 第2版》
[美] 布拉德利·米勒(Bradley N. Miller) 戴维·拉努姆(DavidL. Ranum)|译者:吕能 刁寿钧
以上就是本次Python数据结构学习笔记栈的全部内容,篇幅较长,感谢您的阅读和支持,若有表述或代码中有不当之处,望指出!您的指出和建议能给博主带来很大的动力!!!
Python数据结构学习笔记——栈相关推荐
- Python数据结构学习笔记——队列和双端队列
目录 一.队列的定义 二.队列 实现步骤分析 三.队列的Python实现代码 四.队列的应用 六人传土豆游戏 五.双端队列的定义 六.双端队列 实现步骤分析 七.双端队列的Python实现代码 八.双 ...
- Python数据结构学习笔记——链表:无序链表和有序链表
目录 一.链表 二.无序链表 实现步骤分析 三.无序链表的Python实现代码 四.有序链表 实现步骤分析 五.有序链表的Python实现代码 结语 一.链表 链表中每一个元素都由为两部分构成:一是该 ...
- 数据结构学习笔记——栈(1)定义理解
写在前面的话--努力不晚 博主是某985学校数字媒体技术专业的本科在读生,即将成为大四狗,今后打算国内读研. 因为数媒专业设置的缘故,前两年尝试了很多艺术和设计方面的东西:素描.设计原理.UI.视频剪 ...
- Python数据结构学习笔记——树和图
目录 一.树的概念 二.二叉树的实现 (一)列表的列表 (二)结点与引用 三.图的概念 四.图的实现 (一)邻接矩阵 (二)邻接表 一.树的概念 树是一种数据结构,树由结点及连接结点的边组成,每个树有 ...
- 数据结构学习笔记——栈和队列
4 栈与队列 栈是限定仅在表尾进行插入和删除操作的线性表.队列是只允许在一端进行插入操作.而在另一端进行删除操作的线性表. 4.1 栈的定义 栈(stack)是限定仅在表尾进行插入和删除操作的线性 ...
- python数据结构学习笔记(五)
5 Array-Based Sequence 5.2.1 referential arrays 5.2.2 compact arrays in python array.array 5.3 dynam ...
- Python数据结构学习笔记——搜索与排序算法
目录 一.搜索 (一)搜索的方法 (二)顺序搜索 (三)二分搜索 二.排序 内排序和外排序 (一)冒泡排序 (二)选择排序 (三)插入排序 (四)希尔排序 (五)归并排序 (六)快速排序 总结 一.搜 ...
- 数据结构学习笔记——栈的基本知识和顺序存储结构实现栈(顺序栈)
目录 一.栈 (一)栈的概念 (二)栈的排列 (三)共享栈 (四)栈的常见应用 二.顺序栈的定义 三.顺序栈的初始化 四.判断顺序栈是否为空栈 五.判断顺序栈是否为满栈 六.进栈(插入操作) 七.出栈 ...
- 408数据结构学习笔记——栈和队列的应用、特殊矩阵的压缩
目录 1.栈在括号匹配中的应用 2.栈在表达式求值中的运用 2.1.中缀表达式转换后缀表达式 2.2.后缀表达式的计算方法 2.3.中缀表达式转换前缀表达式 2.4. 中缀表达式转后缀表达式(机算- ...
最新文章
- js 定位当前城市之接口定位(搜狐、新浪、百度、腾讯API)
- Spark基础学习笔记11:Scala运算符
- 安装工程造价课程设计_安装工程造价课程设计的图纸-上海装修报价
- c# DESEncrypt 加密、解密算法
- Java的Exception解析
- mybatisplus service insert 空指针_c++ 图解层序遍历和逐层打印智能指针建造的二叉树...
- 阿里OSS对象存储,实现图片上传进度显示ProgressListener;
- C#程序加密工具.Net Reactor教程
- python循环抓取图片_【Python系列】第2篇:批量下载图片
- Python爬虫_宅男福利?妹纸勿点__一蓑烟雨任平生
- 计算机实训学校目的和要求,计算机实习目的和要求
- 汉字编码对照表(gb2312/Big5/GB2312)
- 分布式系统的完整介绍
- ASP.NET学习笔记(二)——一般处理程序之图片上传
- shell脚本实战之坦克大战小游戏
- 树莓派第一次使用WIN10电脑远程连接(无显示器)
- W3C 发布 EME 标准,EFF 退出 W3C
- 把我本科2年爬过的坑,送给高考完想要选计算机专业的你,成为人们眼中的大神吧
- python3入门笔记
- matlab 多子图_matlab 多子图的绘画
热门文章
- RabbitMQ Network Partitions
- 微软或在开发自己的 CPU、TikTok 发布电视版本、索尼撤下《赛博朋克2077》并为玩家退款|Decode the Week...
- 范醒哲:敬畏自然 渴望技术 —— 新冠肺炎后对网络数据传输能力的思考
- 探秘云游戏背后实时音视频技术实践
- 音视频技术开发周刊 81期
- 『每周观察』:“在线抓娃娃”开启新娱乐窗口
- nginx源码分析—数组结构ngx_array_t
- Hyperledger Fabric 1.0发布:基于区块链的开源分布式账本
- RxJava 2.0的基本使用
- go语言判断手机号归属地