写一个程序,使得该程序能够完成个位数的四则运算,但要用到栈的基本操作。既然是实验就会有它的目的和要求。
实验目的:1.掌握栈的定义及实现方法;
2.掌握利用栈求解算术表达式的方法。
实验要求:1.使用链式存储结构完成栈的各种基本操作;
2.补充完成In©, Preced(t1,t2), Operate(a,theta,b)三个函数。
栈是一种先进后出的线性表,既然是线性表,就可以有顺序形式,即顺序栈;也可以有链式形式,即链栈。本实验是要求用链式存储结构,所以以下内容就是关于链栈的表示和实现,以及用链栈实现个位数的四则运算。
初始化:即构造一个空栈,因为没必要设置头结点,所以直接将栈顶指针置空即可。
【算法描述】
Status InitStack(LinkStack &S)
{
S=NULL;
return OK;
}
入栈:链栈在入栈前不需要判断栈是否满,然而顺序栈的入栈操作是要判断的,链栈只需要为入栈元素动态分配一个结点空间。
【算法描述】
Status Push(LinkStack &S,SElemType e)
{
p=new StackNode;
p->data=e;
p->next=S; //将新结点插入栈顶
S=p; //修改栈顶指针为p
return OK;
}
出栈:出栈前需要判空,跟顺序栈时一样的,但是,链栈跟链表的删除一样,出栈后需要释放栈顶元素的栈顶空间。
【算法描述】
Status Pop(LinkStack &S,SElemType e)
{
if(S==NULL) return ERROR; //栈为空的情况
e=S->data;
p=S; //临时保存,以备释放;
S=S->next; //修改栈顶指针
delete p; //释放原栈顶元素空间
return OK;
}
取栈顶元素:与顺序栈一样,当栈非空时,此操作返回当前栈顶元素的值,栈顶指针S保持不变。
【算法描述】
SElemType GetTop(LinkStack S)
{
if(S!=NULL)
return S->data;
}
链栈的基本操作就是以上这些,根据上面的基本操作以及要补充的代码(这些代码在后面的程序中有,里面的代码也简单,应该能看得懂),实现实验要求的完整代码如下:
【完整代码】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
typedef int Status;
typedef char SElemType;
typedef struct StackNode
{
SElemType date;
struct StackNode *next;
}StackNode,*LinkStack;
Status InitStack (LinkStack &S)
{
S=NULL;
return OK;
}
Status Push(LinkStack &S,SElemType e)
{
LinkStack p;
p=new StackNode;
p->date=e;
p->next=S;
S=p;
return OK;
}
Status Pop(LinkStack &S,SElemType &e)
{
LinkStack p;
if(S==NULL) return ERROR;
e=S->date;
p=S;
S=S->next;
delete p;
return OK;
}
SElemType GetTop(LinkStack S)
{
if(S!=NULL)
return S->date;
}
Status In(char ch)
{
switch(ch) //判断c是否为运算符
{
case '+':
return OK;
case '-':
return OK;
case '*':
return OK;
case '/':
return OK;
case '(':
return OK;
case ')':
return OK;
case '#':
return OVERFLOW;
default:
return ERROR;
}
}
//比较运算符的优先级
SElemType Precede(SElemType a,SElemType b)
{
if(b=='+')
{
if(a=='('||a=='#')
return '<';
return '>';
}
if(b=='-')
{
if(a=='('||a=='#')
return '<';
return '>';
}
if(b=='*')
{
if(a=='*'||a==')'||a=='/')
return '>';
return '<';
}
if(b=='/')
{
if(a=='*'||a==')'||a=='/')
return '>';
return '<';
}
if(b=='(')
return '<';
if(b==')')
{
if(a=='(')
return '=';
return '>';
}
if(b=='#')
{
if(a=='#')
return '=';
return '>';
}
}
SElemType Operate(SElemType a,SElemType theta,SElemType b)
{
SElemType c;
a=a-'0';
b=b-'0';
switch(theta)
{
case '+':
c=a+b+'0';break;
case '-':
c=a-b+'0';break;
case '*':
c=a*b+'0';break;
case '/':
c=a/b+'0';break;
}
return c; //返回计算结果
}
char EvaluateExpression() //运算过程
{
LinkStack OPTR,OPND;
char ch,theta,a,b,x;
InitStack(OPND); //初始化运算符栈
InitStack(OPTR); //初始化操作数栈
Push(OPTR,'#');
scanf("%c",&ch);
while(ch!='#'||GetTop(OPTR)!='#')
{
if(!In(ch))
{
Push(OPND,ch);
scanf("%c",&ch); //ch不是运算符则进OPND栈
}
else
switch(Precede(GetTop(OPTR),ch)) //比较OPTR的栈顶元素跟ch的优先级
{
case '<':
Push(OPTR,ch);
scanf("%c",&ch); //读取下一字符ch
break;
case '>':
Pop(OPTR,theta);
Pop(OPND,b);
Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
case '=':
Pop(OPTR,x);
scanf("%c",&ch);
break;
} //switch
} //while
return GetTop(OPND); //OPND 栈顶元素即为表达式的求值结果
}
int main()
{
char w;
printf("请输入算术表达式,并以#号结束。\n");
w=EvaluateExpression(); //将运算结果赋值给w
w=w-48; //将字符转换成数字
printf("the result of expression is: %d\n",w);
printf("\n\n请按任意键退出!");
return 0;
}
程序运行及试验结果:
注意:此处我输入的括弧只能是英文的。
看不懂的可以在下方留言,如果我看到,可以给你们解答。
【参考文献】:《数据结构》(C语言版|第2版)严蔚敏 李冬梅 吴伟民编著
来源:CSDN
作者:闆運厷
链接:https://blog.csdn.net/qq_43873385/article/details/103990650