表达式求值(无括号)

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

算法思想

(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(b, (char)op, a);
                        Push(ovs, t);
                        break;
            }
        }
    }
    t = GetTop(ovs);//取栈顶元素,返回值 
    return t; 
}



int main(){
    int ans = ExpEvaluation();
    printf("%d
", ans);
    return 0;
}
种一棵树最好的时间是十年前,其次是现在。
原文地址:https://www.cnblogs.com/HyattXia/p/9784987.html