我们先看看后缀表达式:9 3 1 -3 *+10 2 / +
规则:从左到右遍历表达式的每个数字和字符,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,运算结果进栈,一直到获得最终结果
中缀表达式“9+(3-1)* 3 + 10 / 2”叫中缀表达式
规则:从左到右遍历中缀表达式的每个数字和字符,是数字则输出,即成为后缀表达式的一部分;若是符号或优先级不高于栈顶符号(乘除优先加减)则栈顶元素一次出栈并输出,并将当前符号进栈,一直到输出最终结果为止。
其实也就是两步:
1.将中缀表达式转化为后缀表达式
2.将后缀表达式进行运算得出结果
.
.
下面来看代码思路详解(思路和代码都是自己想的,可能会有些错误,谢谢指出)
思路:先定义两个栈,分别为stack1和stack2,stack1存运算符号,stack2存数字。遍历运算表达式,如果遇到数字就将数字压入stack2中,是符号则判断栈stack1的栈顶元素的和当前遇到的符号进行优先级比较,如果当前遇到的符号优先级不高于栈stack1的栈顶符号的优先级,则将栈stack1的栈顶的符号取出,同时取出栈stack2的栈顶的两数字进行运算,再将遇到的符号压入stack1;如果当前遇到的符号优先级高于栈stack1的栈顶符号的优先级如果,则只进行压入符号到stack1这一操作。
定义两个结构体:一个结构体存符号,另一个结构体存数字
struct sta1 //将符号存入该栈内
{
char element[N];
int top;
}stack1;
struct sta2 //将数字存入该栈内
{
int num[N];
int top;
}stack2;
定义一个函数,该函数执行数字的相关操作,如栈顶两数字加减乘除
void stack2deal(char fu)//将栈stack2中的数字执行相应操作
{
int d1,d2,t;//d1,d2分别储存栈顶的两个数字
d1=stack2.num[stack2.top--];//取出stack2的栈顶元素
d2=stack2.num[stack2.top--];//取出stack2的栈顶元素
//进行相关操作
if(fu=='+')
{
t=d2+d1;
}
else if(fu=='-')
{
t=d2-d1;
}
else if(fu=='*')
{
t=d2*d1;
}
else if(fu=='/')
{
t=d2/d1;
}
stack2.num[++stack2.top]=t;//将得到的结果压入栈stack2中
}
下面为压入弹出操作,即增加和删除操作
void push(char x) //将元素压入栈内
{
if(stack1.top==N) //栈满
return ;
stack1.element[++stack1.top]=x;
}
char pop() //将元素弹出栈内
{
if(stack1.top!=-1) //有元素
return stack1.element[stack1.top--];
}
下面为字符操作,即遍历字符串,遇到哪个字符就执行哪个字符的操作
void add() //如果字符为"+",则执行该函数
{ //优先级问题,如果stack1的顶部符号优先级高于或等于"+"
//则将stack1的顶部元素弹出并执行顶部元素的操作
//即void stack2deal(char fu)函数,并将"+"压入stack1中
//如果stack1的顶部没有元素或者顶部元素优先级低于"+"
//则只进行将"+"压入stack1的操作
if(stack1.element[stack1.top]!='('&&stack1.top!=-1)//因为"+"的优先级是最低的,所有只有栈顶为空或者栈顶为"("才不执行该操作
stack2deal(pop());
push('+');
}
void sub() //如果字符为"-",则执行该函数
{
//该操作与"+"的操作类似
if(stack1.element[stack1.top]!='('&&stack1.top!=-1)
stack2deal(pop());
push('-');
}
void mul()//如果字符为"*",则执行该函数
{
//优先级问题,如果stack1的顶部元素优先级高于或等于"*"
//则将stack1的顶部元素弹出并执行顶部元素的操作
//即void stack2deal(char fu)函数,并将"*"压入stack1中
//如果stack1的顶部没有元素或者优先级低于"*"
//则只进行将"*"压入stack1的操作
if(stack1.element[stack1.top]=='*'||stack1.element[stack1.top]=='/')//因为"*"的优先级是最高的,所有只有栈顶是"*"或者"/"才执行下面语句
stack2deal(pop());
push('*');
}
void div()//如果字符为"/",则执行该函数
{
//该操作与乘法类似
if(stack1.element[stack1.top]=='*'||stack1.element[stack1.top]=='/')
stack2deal(pop());
push('/');
}
void headquote()//如果字符为"(",则执行该函数
{
push('(');//入栈stack1
}
void backquote()//如果字符为")",则执行该函数
{
//直到stack1的顶部为"("则停止循环,并将"("弹出
while(stack1.element[stack1.top]!='(')
{
stack2deal(pop());
}
//弹出"("
pop();
}
int datadeal(int i) //如果是字符是数字,则将数字压入stack2中
{
//因为我们使用的是字符串,所有我们要将字符串中的字符数字转化为数字
int j,t=0;
for(j=i;a[j]>='0'&&a[j]<='9';j++)
t=t*10+(a[j]-'0');
//将该数压入stack2中
stack2.num[++stack2.top]=t;
return j-1;//返回字符串的位置
}
下面为字符串遍历完后的操作
void cleanstack1()
//字符串遍历完后,栈stack1中可能还有剩余运算符
//将栈stack1中剩余的运算字符弹出并执行相应操作
{
while(stack1.top!=-1)
{
stack2deal(stack1.element[stack1.top]);
stack1.top--;
}
}
详细代码如下
#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 1000
char a[N]; //待输入的四则表达式
struct sta1 //将非数字的字符存入该栈内
{
char element[N];
int top;
}stack1;
struct sta2 //将字符为数字的字符存入该栈内
{
int num[N];
int top;
}stack2;
void push(char x) //将元素压入栈内
{
if(stack1.top==N)
return ;
stack1.element[++stack1.top]=x;
}
char pop() //将元素弹出栈内
{
if(stack1.top!=-1)
return stack1.element[stack1.top--];
}
void add() //如果字符为"+",则执行该函数
{ //优先级问题,如果stack1的顶部符号优先级高于或等于"+"
//则将stack1的顶部元素弹出并执行顶部元素的操作,并将"+"压入stack1中
//如果stack1的顶部没有元素或者优先级低于"+"
//则只进行将"+"压入stack1的操作
if(stack1.element[stack1.top]!='('&&stack1.top!=-1)
stack2deal(pop());
push('+');
}
void sub() //如果字符为"-",则执行该函数
{
//该操作与"+"的操作类似
if(stack1.element[stack1.top]!='('&&stack1.top!=-1)
stack2deal(pop());
push('-');
}
void mul()//如果字符为"*",则执行该函数
{
//优先级问题,如果stack1的顶部符号优先级高于或等于"*"
//则将stack1的顶部元素弹出并执行顶部元素的操作,并将"*"压入stack1中
//如果stack1的顶部没有元素或者优先级低于"*"
//则只进行将"*"压入stack1的操作
if(stack1.element[stack1.top]=='*'||stack1.element[stack1.top]=='/')
stack2deal(pop());
push('*');
}
void div()//如果字符为"/",则执行该函数
{
//该操作与乘法类似
if(stack1.element[stack1.top]=='*'||stack1.element[stack1.top]=='/')
stack2deal(pop());
push('/');
}
void headquote()//如果字符为"(",则执行该函数
{
push('(');
}
void backquote()//如果字符为")",则执行该函数
{
//直到stack1的顶部为"("则停止循环,并将"("弹出
while(stack1.element[stack1.top]!='(')
{
stack2deal(pop());
}
//弹出"("
pop();
}
int datadeal(int i) //如果是字符是数字,则将数字压入stack2中
{
//因为我们使用的是字符串,所有我们要将字符串中的字符数字转化为数字
int j,t=0;
for(j=i;a[j]>='0'&&a[j]<='9';j++)
t=t*10+(a[j]-'0');
//将该数压入stack2中
stack2.num[++stack2.top]=t;
return j-1;//返回字符串的位置
}
void stack2deal(char fu)//将栈stack2中的数字执行相应操作
{
int d1,d2,t;
d1=stack2.num[stack2.top--];
d2=stack2.num[stack2.top--];
if(fu=='+')
{
t=d2+d1;
}
else if(fu=='-')
{
t=d2-d1;
}
else if(fu=='*')
{
t=d2*d1;
}
else if(fu=='/')
{
t=d2/d1;
}
stack2.num[++stack2.top]=t;//将得到的结果压入栈stack2中
}
void cleanstack1()
//字符串遍历完后,将栈stack1中剩余的运算字符弹出并执行相应操作
{
while(stack1.top!=-1)
{
stack2deal(stack1.element[stack1.top]);
stack1.top--;
}
}
int main()
{
while(~scanf("%s",a))//输入运算表达式
{
stack1.top=stack2.top=-1;//初始2个栈的顶部都为-1
int len=strlen(a),i;
for(i=0;i<len;i++)
{
//执行相关操作
if(a[i]=='+')
add();
else if(a[i]=='-')
sub();
else if(a[i]=='*')
mul();
else if(a[i]=='/')
div();
else if(a[i]=='(')
headquote();
else if(a[i]==')')
backquote();
else
{
i=datadeal(i);
}
}
cleanstack1();//清理栈stack1
printf("%d\n",stack2.num[stack2.top]);//输出最后结果
}
return 0;
}