表达式求值(无括号)

Posted hyattxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表达式求值(无括号)相关的知识,希望对你有一定的参考价值。

对于自然数的表达式求值,操作有加、减、乘、除和幂运算,分别用+,-, *, /,^来表示,为方便运算,加入#运算符,其运算优先级最低,由于运算符优先级不一样,可以利用栈实现此操作。

算法思想

(1)规定运算符的优先级表

(2)设置两个栈:OVS(运算数栈)和OPTR(运算符栈),为了操作方便可以先在OPTR栈中先放一个#运算符

(3)自左向右扫描,进行如下处理:

若遇到运算数则金OVS栈;若遇到运算符则与OPTR栈顶运算符进行比较:

?如果当前运算符的优先级大于OPTR栈顶运算符的优先级,则当前运算符进入OPTR栈;

?如果当前运算符的优先级大于等于OPTR栈顶运算符的优先级,则OPTR退栈一次,得到栈顶运算符op, 连续退栈OVS两次,得到运算数a和b,执行op运算,得到结果T,将T进OVS栈。

 

可以自己画一个表达式两个栈的变化图,有助于理解

 

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<stdbool.h>

typedef struct node{
    int data;//无论对于运算符还是运算数,都用int型变量来保存 
    node *next;
}LinkStackNode, *LinkStack;

void InitStack(LinkStack *S){//初始化链栈 
    *S = (LinkStack)malloc(sizeof(LinkStackNode));
    (*S)->next = NULL;
}

int Push(LinkStack top, int x){// 进栈操作 
    LinkStackNode *temp;
    temp = (LinkStackNode*)malloc(sizeof(LinkStackNode));
    if(temp == NULL) return 0;
    temp->data = x;
    temp->next = top->next;
    top->next = temp;
    return 1;
}

int Pop(LinkStack top, int *x){//出栈操作 
    LinkStackNode *temp;
    temp = top->next;
    if(temp == NULL) return 0;
    *x = temp->data;
    top->next = temp->next;
    free(temp);
    return 1;
}

int GetNum(char ch){//返回字符对应的数字 
    return ch - 0;
}

bool IsEmpty(LinkStack top){//栈为空返回假 
    if(top->next == NULL) return false;
    return true;
}

int GetTop(LinkStack top){//返回栈顶元素 
    if(top->next == NULL) return 1;
    return top->next->data;
}

char Compare(char ch1, char ch2){//实现运算符优先级比较 
    switch(ch1){
        case #:
        switch(ch2){
            case #: return =;
            case +:
            case -:
            case *:
            case /:
            case ^: return <;
        }
        case +:
            switch(ch2){
                case #: return >;
                case +:
                case -: return =;
                case *:
                case /:
                case ^: return <;
            }
        case -:
            switch(ch2){
                case #: return >;
                case +:
                case -: return =;
                case *:
                case /:
                case ^: return <;
            }
        case *:
            switch(ch2){
                case #:
                case +:
                case -: return >;
                case *:
                case /: return =;
                case ^: return <;
            }
        case /:
            switch(ch2){
                case #:
                case +:
                case -: return >;
                case *:
                case /: return =;
                case ^: return <;
            }
        case ^:
            switch(ch2){
                case #:
                case +:
                case -:
                case *:
                case /: return >;
                case ^: return =;
            }
    }
}

int Calculate(int a, char op, int b){//计算 a op b 的值 
    int c;
    switch(op){
        case -: c = a - b; break;
        case +: c = a + b; break;
        case *: c = a * b; break;
        case /: c = a / b; break;
        case ^: c = pow(a, b); break;
        default : c = 0;
    }
    return c;
}

int ExpEvaluation(){//实现 
    LinkStack ovs, optr;
    InitStack(&ovs);
    InitStack(&optr);
    Push(optr, (int)#);
    printf("

Please input an expression(Ending with ‘#‘):
");
    char ch = getchar();
    int num = 0, a, b, t, op, zan;
    while(ch != # || (char)GetTop(optr) != #){
        while(ch >= 0 && ch <= 9){//如果数字不是一位数字,便把字符转化为数字 
            num = num * 10 + GetNum(ch);
            ch = getchar();
        }
        if(num != 0){//如果num不为0便进OVS栈 
            Push(ovs, num);
            num = 0;//把num置零 
        }
        else{
            switch(Compare(ch, (char)GetTop(optr))){//对运算符优先级进行比较,实现对应三种关系的操作 
                case >: Push(optr, (int)ch); ch = getchar(); break;
                case =:
                case <: Pop(optr, &op); 
                        Pop(ovs, &a);
                        Pop(ovs, &b);
                        t = Calculate(a, (char)op, b);
                        Push(ovs, t);
                        break;
            }
        }
    }
    t = GetTop(ovs);//取栈顶元素,返回值 
    return t; 
}



int main(){
    int ans = ExpEvaluation();
    printf("%d
", ans);
    return 0;
}

 

以上是关于表达式求值(无括号)的主要内容,如果未能解决你的问题,请参考以下文章

代码随想录算法训练营第11天 | ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值

中缀表达式求值

中缀表达式求值

表达式求值

中缀表达式转换成后缀表达式并求值

表达式求值