栈-表达式求值

表达式求值是程序设计语言编译中的一个最基本问题。它的实现是栈应用的有一个典型例子。

这里使用算符优先法。

输入:一个表达式.

输出:输出其后缀表达式并且进行表达式的求值。

运行结果:

算法思想:

拿当前扫描的运算符号与上一个比较优先级,当前扫描符号低或相等则进行上一个运算,需取最近的两个数。否则扫下个。

设操作符栈与操作数栈,运算符栈最初压如‘#’,逐个扫描符号。遇操作数则直接入栈,继续读下一字符。遇运算符则与栈顶运算符比较优先级,当前运算符优先级高,前面的运算还不应执行,则当前运算符入栈,读下一符号。否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,开始下次循环,不扫描新符号,重新比较刚才扫描到的运算符,与新栈顶运算符。如此重复直到栈顶运算符与当前符号均为#。

后缀表达式:对于扫描到的数字除了入数栈之外,同时入到另一个用于求后缀表达式的PEXP,当执行一次运算时,将执行的算符同时压入PEXP中,所有运算结束后,从栈底到栈顶输出序列即为表达式的后缀表达式。

现在还有一个问题:表达式中肯定有小数或者多位数,不一定是个位数,我们需要表示它们。首先定义一个c1字符表示上一个字符,如果上一个字符是.说明正在读取一个小数,然后用flag计算小数的位数,出现小数后就修改栈顶元素。反之,如果上一个元素是整数,说明读取的是一个多位数,就计算并修改栈顶元素。如果是个位数直接压入栈即可。

首先给出辅助函数:

判定运算符的栈顶运算符与读入的运算符之间优先关系。

char Precede(char c1,char c2){
	//判定运算符的栈顶运算符与读入的运算符之间优先关系
    char c;
    switch(c1){
        case '+':
        case '-':
	    switch(c2){
	        case '+':
                case '-':
	        case ')':
                case '#':
		    c='>';
                break;
	        default:
		    c='<';
	    }
        break;
        case '*':
        case '/':
            if(c2=='(')
		c='<';
	    else
		c='>';
            break;
        case '(':
	    if(c2==')')
		 c='=';
	    else
		 c='<';
            break;
        case ')':
	    c='>';
            break;
        case '#':
	    if(c2=='#')
		c='=';
	    else
		c='<';
    }
    return c;
}

进行二元运算 a theta b。

double Operate(double a,char theta,double b){
	//进行二元运算 a theta b
	double sum;
    switch(theta)
    {
       case '+':
	   sum=a+b;
	   break;
       case '-':
	   sum=a-b;
	   break;
       case '*':
           sum=a*b;
           break;
       case '/':
           sum=a/b;
	   break;
    }
    return sum;
}

判断是不是运算符.

Status In(char c,char *OP){
    //判断是不是运算符
    for(int i=0;i<7;i++)
       if(c==OP[i])   //是运算符
          return TRUE;
    return FALSE;
}

算法实现:

double EvaluateEvaluation(char * s){
    //进行多项式的求值以及后缀表达式的输出
    int i=0,len,flag=0;
    double a,b,sum;
    char c1=s[0],e;
    char OP[7]={'+','-','*','/','(',')','#'}; //运算符数组
    SqStack<char> OPTR; //运算符栈
    SqStack<double> OPND; //运算数栈
    SqStack<char> PEXP;     //后缀表达式栈
    InitStack(OPTR); //初始化栈
    InitStack(OPND);
    InitStack(PEXP);
    len=strlen(s);
    s[len]='#';
    s[len+1]='\0';
    Push(OPTR,'#');//压入一个‘#’
    while(s[i]!='#'||GetTop(OPTR)!='#'){ //扫描每一个字符 如果同为‘#’退出循环
        if(!In(s[i],OP)){ //如果不是运算符
            Push(PEXP,s[i]);
	    if(In(s[i+1],OP)) //如果后一个字符是运算符压入一个空格
		Push(PEXP,' ');
            if(c1=='.') //如果上一个字符是小数点
	        flag++;
	    if(flag) {
		SetTopElem(OPND,GetTop(OPND)+(double)(s[i]-'0')/pow(10,flag));//修改栈顶元素
		flag++;
            }
            if(s[i]!='.'&&!flag){
                if(!In(c1,OP)&&!StackEmpty(OPND))//如果上一个字符是数字,修改栈顶元素
                    SetTopElem(OPND,GetTop(OPND)*10+s[i]-'0');
                else//否则压入运算数栈
                     Push(OPND,(double)(s[i]-'0'));
	    }
            c1=s[i++]; //读取下一个字符
	}
        else{//如果是运算符
            flag=0;
            switch(Precede(GetTop(OPTR),s[i])){
                 case '>':  //当前运算符优先级低
	             Pop(OPTR,e); //运算符出栈
	             Pop(OPND,b);
                     Pop(OPND,a);
	             Push(PEXP,e);
	             Push(OPND,Operate(a,e,b)); //将计算结果压入运算符栈
                     break;
                 case '=': //优先级相等
	             Pop(OPTR,e); //弹出运算符栈顶元素
	             c1=s[i++];
                     break;
                 case '<':
	             Push(OPTR,s[i]); //当前运算符优先级高 压入运算符栈
	             c1=s[i++];
                     break;
	     }
        }//else
    }//while
    PrintStack(PEXP);//输出后缀表达式
    sum=GetTop(OPND);
    DestroyStack(OPTR);
    DestroyStack(OPND);
    DestroyStack(PEXP);

    return sum; //返回运算数栈顶元素
}//intc

 

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值