什么是堆栈?
堆栈是一种线性结构,也是一种特殊的线性表。
在函数的调用,递归,函数的求值我们都会用到堆栈。
此处引入一个例子:计算机如何进行表达式求值?
给出一道算术表达式5+6/2-34,正确的理解是:5+6/2-34=-4
该题目是由两类对象构成的:
1、运算数,如2,3,4
2、运算符号如加减乘除等
【不同运算符号的优先级不同】
通常,计算时一般使用的是中缀表达式,现在要介绍一个新的概念叫做后缀表达式,两者区别如下:
中缀表达式是我们常规使用的表示方法,而后缀表达式则是将运算符放在操作数的后面,后缀表达式的特点是计算机运算起来非常方便,需要用到栈:计算机处理过程只需要顺序读入,如果遇到数字,则放入栈中,如果遇到运算符,则将两个栈中数字取出进行运算,再将运算结果进栈,一直到获得最终的结果。
比如:62/3-42*+=?
这就是一个后缀表达式,运算过程如下。
T(N)=O(N)
堆栈的抽象数据类型描述
堆栈(stack):具有一定操作约束的线性表。
只在一端(栈顶,top)做插入和删除
插入数据:入栈(push)
删除数据:出栈(pop)
后入先出:Last in first out(LIFO)
抽象数据类型描述如下:
首先创一个空的栈,放入放入放入拿出拿出拿出最后又空了。
push和pop可以穿插进行,且严格按照顺序执行。
栈的顺序存储实现
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成。
top不是一个地址,是一个整型变量。
(1)入栈:
因为是用数组来表示的,首先要判断堆栈满不满,数组是有固定大小的,有界限的。
其中下方的赋值语句其实是做了两件事,因为入栈进入了一个新的元素,所以top要上挪。
(2)出栈:
top=0时说明有一个元素,如果top=-1说明正好没有元素,即堆栈空。
出栈的时候元素要减少,所以top也要相应的发生变化。
假设要用一个数组来表示双堆栈,如果这两个堆栈的栈顶位置分别是top1和top2,那么可以用top1+top2==MaxSize(数组大小)来判别堆栈是否满?
答案是不可以,top1和top2都代表数组下标,所以按题干理解是错误的。
正确的方法应该是使这两个栈分别从数组的两头开始向中间生长,当两个栈道栈顶指针相遇时,表示两个栈都满了
用tag来区分堆栈1和堆栈2.
用tag继续进行判别是对哪个堆栈进行处理,对堆栈1处理时要判别它空不空,对堆栈2处理时也要判别它是否空。
堆栈的链式存储实现
注意:栈的链式存储结构实际上就是一个单链表,叫做链栈,插入和删除操作智能在链栈道栈顶进行,栈顶指针TOP智能在链表的头部。
不能用链表的尾做头部。
结构如下:
操作如下:
插入删除
流程如下:
与昨天课程类似。
注意用链表来实现时不需要判断堆栈满不满,因为数组大小是固定的所以需要面临满不满的问题。
注意问题都与昨天的课程类似。
堆栈应用:表达式求值
将中缀表达式转换为后缀表达式,然后求值。
其他应用:函数调用及递归实现/深度优先搜索/回溯算法等等。