栈和队列
特殊线性表——栈
定义:栈:限定仅在表尾进行插入和删除操作的线性表。
空栈:不含任何数据元素的栈。
允许插入和删除的一端称为栈顶,另一端称为栈底。
操作特性:先进的元素后出去
栈的逻辑结构情况:
注:栈只是对表插入和删除操作的位置进行了限制,并没有限定插入和删除操作进行的时间。
栈的抽象定义
- InitStack
前置条件:栈不存在
输入:无
功能:栈的初始化
输出:无
后置条件:构造一个空栈 - DestroyStack
前置条件:栈已存在
输入:无
功能:销毁栈
输出:无
后置条件:释放栈所占用的存储空间 - Push
前置条件:栈已存在
输入:元素值x
功能:在栈顶插入一个元素x
输出:如果插入不成功,抛出异常
后置条件:如果插入成功,栈顶增加了一个元素 - Pop
前置条件:栈已存在
输入:无
功能:删除栈顶元素
输出:如果删除成功,返回被删元素值,否则,抛出异常
后置条件:如果删除成功,栈减少了一个元素 - GetTop
前置条件:栈已存在
输入:无
功能:读取当前的栈顶元素
输出:若栈不空,返回当前的栈顶元素值
后置条件:栈不变 - Empty
前置条件:栈已存在
输入:无
功能:判断栈是否为空
输出:如果栈为空,返回1,否则,返回0
后置条件:栈不变
//函数需要自己定义
栈的顺序存储结构及实现
顺序栈——栈的顺序存储结构
顺序栈的实现:入栈(操作接口: void Push( T x );
判断是否是空栈(操作接口: bool Empty( )
取栈顶(操作接口: T GetTop( );
出栈(操作接口: T Pop( );
两栈共享空间
两栈共享空间:使用一个数组来存储两个栈,让一个栈的栈底为该数组的始端,另一个栈的栈底为该数组的末端,两个栈从各自的端点向中间延伸。
两栈共享空间
两栈共享空间的实现:插入(操作接口:void Push(int i, T x))
删除(操作接口:T Pop(int i))
链栈:栈的链接存储结构
链栈的实现:插入(入栈)(操作接口: void Push(T x)
删除(出栈)(操作接口: T Pop( )
链栈的析构(链栈的销毁)
注:顺序栈和链栈的比较
时间性能:相同,都是常数时间O(1)。
空间性能:
顺序栈:有元素个数的限制和空间浪费的问题。
链栈:没有栈满的问题,只有当内存没有可用空间时才会出现栈满,但是每个元素都需要一个指针域,从而产生了结构性开销。
结论:当栈的使用过程中元素个数变化较大时,用链栈是适宜的,反之,应该采用顺序栈。
表的表达式
- 中缀表达式求值
- 中缀表达式转化为后缀表达式
- 后缀表达式求值
后缀表达式求值算法:
从左到右对后缀表达式字符串进行处理,每次处理一个符号
1.若遇到数字,入栈
2.若遇到运算符,栈顶两个数字出栈,执行运算符所定义的运算,并将运算结果入栈
3.重复以上的工作,直到表达式结束,此时,栈中的数字代表最终的值。
例:123 30 + 12 6 - / 5 +
中缀表达式求值
表达式的组成:
1.操作数(operand):
操作数既可以是常数, 也可以是被说明为变量或常量;
- 运算符(operator):
运算符可以分为算术运算符、 关系运算符和逻辑运算符三类,不同的运算符有不同的优先级以及结合性
1.界限符(delimiter) :
基本界限符有左右括号和表达式结束符等。 例如:
#(3+4)*5-2#,界限符的优先级相同(左括号和右括号的优先级相同, #的优先级也相同)
重:
运算符优先级表
中缀表达式:操作数栈和运算符栈