栈和队列是是限定插入和删除只能在表的“端点”进行的线性表
栈:后进先出
Insert(S,n+1,x)
Delete(S,n)
常见应用
数制转换、表达式求值、括号匹配的检验、八皇后问题、行编辑程序、函数调用、迷宫求解、递归调用的实现
栈的定义
限定在仅一端(通常是表尾)进行插入和删除的线性表
表尾(an端)称为栈顶Top,表头(a1端)称为栈底Base
例如:栈:s = (a1,a2,a3……,an-1,an)
a1称为栈底元素,an称为栈顶元素
插入元素到栈顶(表尾)的操作称为入栈
从栈顶(表尾)删除最后一个元素的操作称为出栈
逻辑结构
与线性表相同,仍为一对一关系
存储结构
用顺序栈或链栈存储均可,但以顺序栈更常见
运算规则
只能在栈顶运算,且访问结点时依照后进先出的原则
实现方式
关键是编写入栈出栈函数,具体实现依顺序栈或链栈的不同而不同
队列:先进先出
Insert(Q,n+1,x)
Delete(Q,1)
常见应用
- 脱机打印输出:按申请的先后顺序依次输出
- 多用户系统中,多个用户排成队,分时的循环使用cpu和主存
- 按用户的优先级排成多个队,每个优先级一个队列
- 实时控制系统中,信号按接收的先后顺序依次处理
- 网络电文传输,按到达的时间先后顺序依次进行
队列定义
只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表(头删尾插)
在表一端插入(表尾),在另一端(表头)删除
Q=(a1,a2,a3…an)
a1为队头,an为队尾
逻辑结构
与同线性表相同,仍为一对一关系
存储结构
顺序队或链队,以循环顺序队列更常见
运算规则
只能在队首和队尾运算,且访问结点时依照先进先出(FIFO)的原则
实现方式
掌握入队和出队操作,具体实现依顺序或链队的不同而不同
典型案例
进制转换
十进制整数N向其他进制数d(二、八、十六)的转发时计算机实现计算的基本问题
转换法则:除以取倒余
算法原理:n=(n div d)*d + n mod d
div为整除运算,mod为求余运算
括号匹配的检验
假设表达式中允许包含两种括号:圆括号和方括号
嵌套顺序随意
( [ ] ( ) )或[ ( [ ] [ ] ) ]为正确格式
[ ( ] ) ]或( [ ( ) )或( ( ) ] )为错误格式\
可以利用一个栈结构保存每个出现的左括号,遇到右括号时,从栈中弹出左括号,检验匹配情况
在检验过程中,若遇到以下几种情况之一,就可以得出括号不匹配的结论
- 当遇到某一个右括号时,栈已空,说明到目前为止,右括号多于左括号
- 从栈中弹出的左括号与当前检验的右括号类型不同,说明出现了括号交叉的情况
- 算术表达式输入完毕,但栈中还有没有匹配的左括号,说明左括号多于右括号
表达式求值
由运算符优先级确定运算顺序的队表达式求值算法——算符优先算法
表达式的组成:
- 操作数:常数
- 运算符:算数运算符、关系运算符和逻辑运算符
- 界限符:左右括弧和表达式结束符
任何一个算数表达式都由操作数(常数、变量)、算数运算符(+、-、*、/)和界限符(括号、表达式结束符#、虚设的表达式起始符#)组成,后两者统称为算符
需要设置两个栈:
一个是算符栈,用于寄存运算符、
另一个称为操作数栈,用于寄存运算数和运算结果
- 求值的处理过程是自左至右扫描表达式的每一个字符
- 当扫描到的是运算数,则将其压入操作数栈
- 当扫描到的是运算符时
- 若这个运算符比算符栈顶运算符的优先级高,则压入算符栈,继续向后处理
- 若这个运算符比算符栈顶运算符优先级低,则从操作数栈中弹出两个运算数,从算符栈中弹出栈顶运算符进行运算,并将运算结果压入运算数栈
- 继续处理当前字符,直到遇到结束符为止
舞伴问题
假设在舞会上,男士和女士各自排成一队,误会开始时,依次从男队和女队的队头各出一人配成舞伴,如果两队初始人数不相同,则较长的那一对中未配对者等待下一轮舞曲
- 首先构造两个队列
- 依次将队头元素配成舞伴
- 某队为空,则另外一队等待者则是下一舞曲第一个可获得舞伴的人