栈的应用———四则运算表达是求值

本文详细介绍了一种算法,用于将中缀表达式转换为后缀表达式,并通过两个栈实现四则运算的求解过程。算法首先定义了两个栈,一个用于存储运算符号,另一个用于存储数字,然后遍历表达式,根据遇到的字符类型执行相应的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们先看看后缀表达式: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值