第三章栈和队列
从数据结构角度看,栈和队列也是线性表。
栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表。
3.1 栈 stack
限定仅在表尾进行插入和删除操作的线性表。
表尾端 --> 栈顶 top
表头端 --> 栈底 bottom
后进先出 LIFO last in first out
插入元素 --> 入栈
删除元素 --> 出栈
顺序栈
非空栈中的栈顶指针始终在栈顶元素的下一个位置。
3.2 栈的应用举例
3.2.1 数制转换
3.2.2 括号匹配检验
可用“期待的紧迫程度”这个概念来描述。
在算法中设置一个栈;
1、每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;
2、若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的紧迫性都降了一级;
算法开始和结束时,栈都应该是空的。
3.2.3 行编辑程序
遇#退栈
遇@清栈
遇换行输出栈
3.2.4 迷宫求解
栈中所存信息为,坐标+步数+搜寻方向
墙-1
可走0
当前判断的位置与栈顶元素有关
3.2.5 表达式求值
表达式求值算法:
使用两个工作栈:1、运算符栈,2、操作数栈。
基本思想:
1、首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;
2、依次读入表达式的每个字符,若是操作数则进操作数栈,若是运算符,则和运算符栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕。栈顶高则计算,栈顶低则压栈。
符号 + - * / ( )
栈顶
+ > + - )
- > + - )
* > * / + - )
/ > * / + - )
( < all = )
3.3 栈与递归的实现
栈:函数调用
调用函数和被调用函数之间的链接及信息交换需通过栈来进行
递归函数
函数中有直接或间接调用自身函数的语句
条件:1、降阶;2、有出口。
编译软件开辟的栈空间是有限的,当递归调用时,嵌套的层次往往很多,可能发生栈溢出的现象。
3.4 队列
队列 queue:先进先出(First In First Out,FIFO)的线性表。
在表的一端进行插入,而在另一端删除元素。
队尾 rear:允许插入的一端
队头 front:允许删除的一端
典型例子:操作系统中的作业排队
双端队列:限定插入和删除操作在表的两端进行的线性表。
两端插入,一端删除;
两端删除,一端插入;
从插入端删除(栈底相连的栈)。
顺序队列(循环队列):
初始化建空队列时,令front=rear=0
插入队尾,尾指针增1
删除队头,头指针增1
在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾的下一个位置
循环队列:
1、另设一个标志位以区别队列是空还是满;
2、少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置”作为队列呈满的标志。
头尾指针对存储空间MAX_QSIZE求余,形成循环队列。
如果用户的应用程序中设有循环队列,则必须为它设定一个最大队列长度;
若用户无法预估所用队列的最大长度,则采用链队列。