实验三 栈的应用
1.实验目的:
熟悉栈的定义,栈的特点以及栈的基本操作。能够根据实际情况选择合适的存储结构,解决实际问题。
2.实验内容:
对任意给定的一个中缀算术表达式,输出等价的后缀形式。
3.正文部分
①什么是栈
栈也称为堆栈,是一种先进后出,删除和插入都在栈顶操作的线性表。
特性:先进后出,后进先出。
最先放入栈的最后被拿出来,最后放入栈的内容最先被拿出来。
栈的插入
push():在栈顶插入元素
栈的删除
push():在栈顶移除一个元素,并将栈数-1
②栈的基本操作
InitStack(&S) 操作结果:构造一个空栈S。
首先分配好一些内存,之后让栈顶等于栈底(栈内无任何元素)
void Init(SqStack s)
{
s.base=(int *)malloc(size*sizeof(int));
s.top=s.base;
s.stacksize=size;
}
Push(&S,e) 操作结果:插入元素e为新的栈顶元素
初始条件:栈S已存在
向栈顶申请内存+1,再让栈顶元素成为e
void push(SqStack s,int e)
{
if(s.top-s.base>s.stacksize)//如果栈内元素未满
{
s.base=(int *)realloc(s.base,(s.stacksize+incresize)*sizeof(int));
s.top=s.base+s.stacksize;
s.stacksize+=incresize;
}
*s.top++=e;
}
Pop(&S, &e) 操作结果:删除S的栈顶元素,并用e返回其值
初始条件:栈S已存在且非空
栈顶元素-1
void pop(SqStack s,int e)
{
if(s.top!=s.base)
{
e=*(--s.top);
}
cout<<e<<endl;
}
打印函数
输出所有数组
void Print(SqStack *s)
{
int *temp;
temp =s->top;//top
while(temp!=s->base)
{
temp--;
printf("%d",*temp);
}
}
③栈的应用——数制转换
算法原理:N=(N div d)×d+N mod d
例:十进制转八进制
十进制1348转八进制2504
N | N div 8 | N mod |
---|---|---|
1348 | 168 | 4 |
168 | 21 | 0 |
21 | 2 | 5 |
2 | 0 | 2 |
计算顺序由上至下 输出顺序由下至上
void conversion()
{
InitStack(S);
scanf("%d",N);
while(N){
Push(S,N%8);
N=N/8;
}
while(!StackEmpty(S)){
Pop(S,e);
printf("%d",e);
}
}
④栈的应用——括号匹配的检验
检验括号是否匹配的方法:可用“期待的急迫程度”这个概念来描述。
[ ( [ ] [ ] ) ] |
---|
1 2 3 4 5 6 7 8 |
1对应8 2对应7 3对应4 5对应6
出现不匹配的三种可能情况:
1.到来的右括弧不是所“期待”的;
2.到来的是“不速之客”
3.直到结束,也没有到来所期待的括弧;
-
凡出现左括弧,则进栈;
-
凡出现右括弧,首先检查栈是否为空
若栈空,则表明“右括弧”多余
否则和栈顶元素比较
若相匹配,则“左括弧出栈”
否则表明不匹配;
-
表达式检验结束时,若栈空,则表明表达式中匹配正确,
否则表明“左括弧”有余;
⑤栈的应用——表达式求值
表达式的三种标识方法:
Exp = S1 + OP + S2(操作数1 + 操作符 + 操作数2)
前缀表示法:OP + S1 + S2
中缀表示法:S1 + OP + S2
后缀表示法:S1 + S2 + OP
大众使用的通常是中缀表示法。
例:
Exp=a × b + (c - d / e) × f
前缀式: + × a b × -c/d e f
中缀式: a × b + c - d / e × f
后缀式: a b × c d e / - f × +
-
后缀式求值:先找运算符,再找操作数。
一般找到运算符后对应的前面两个(未被处理过的)就是该操作符的对应操作数,如果前面含有已经处理过的操作数,那就把处理过后的两个操作数看成一个,往前数两个就是了。
⑥栈的应用——栈的递归调用
递归函数:一个直接调用自己或通过一系列的调用语句间接地调用自己的函数。
#include<stdio.h>
int f(int m)
{
if(m==1)
return 1;
else
{
printf("m=%d\n",m);
return f(m-1);
}
}
int main()
{
int n;
int f(int m);
printf("请输入一个大于1的数");
scanf("%d",&n);
printf("%d\n",f(n));
return 0;
}
⑦栈的实现
-
顺序栈:指向表尾的指针可以作为栈顶指针
#define STACK_INIT_SIZE 100 typedef struct{ SElemType *base; SElemType *top; int stacksize; }SqStack;
构造一个最大空间为maxsize的空顺序栈S:
Status InitStack (SqStack &S,int maxsize)
{
S.base=new ElemType[maxsize];
if(!S.base) exit (OVERFLOW);//存储分配失败
S.top = S.base;
S.stacksize=maxsize;
return OK;
}
-
链栈
线性表有顺序存储结构和链式存储结构,栈属于线性表的一种,也具有顺序存储结构和链式存储结构
⑧中缀表达式转后缀表达式
(a+b)→(ab+)
中缀表达式运算规则:优先级高的先算,相同优先级的运算符顺序是从左往右。
后缀表达式特点:数字的顺序与中缀一样,运算顺序根据从左到右遇到运算符的顺序进行。(出现的顺序)
转换核心思想:比较相邻的两个运算符,优先级高的先算
注意要点:
1.数字可能是多位数,也可能是小数;
2.数字前面可能有正号或者负号
完整源码下载:数据结构——栈的应用