• 带括号的表达式求值


    问题和上一篇博客一样,只是在表达式中加入了括号。

    思路和上一篇博客的差异不大,只是在处理左右括号的优先级时需要注意一下:

    1.左括号的优先级仅高于#;

    2.但是遇见左括号时,不用和OPTR栈顶元素进行优先级比较,直接强制进OPTR栈;

    3.遇到右括号,退OVS栈两次,退OPTR栈一次,进行相应的运算操作,将计算结果压入OVS栈,直到OPTR栈顶元素时左括号为止,并将左括号弹出OPTR栈;

     

    代码如下:

    #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;
    }
    
    /*进行运算符优先级比较,用表列出所有可能出现的情况,
    ch1对应行,ch2对应列,每次找到对应的位置,直接返回
    优先级比较结果*/ 
    char Compare(char ch1, char ch2){
        int i, j;
        char rela[7][7] = {{'=', '<', '<', '<', '<', '<', '<'},
                           {'>', '=', '=', '<', '<', '<', '>'},
                           {'>', '=', '=', '<', '<', '<', '>'},
                           {'>', '>', '>', '=', '=', '<', '>'},
                           {'>', '>', '>', '=', '=', '<', '>'},
                           {'>', '>', '>', '>', '>', '=', '>'},
                           {'>', '<', '<', '<', '<', '<', '='},
                        };
        switch(ch1){
            case '#': i = 0;break;
            case '+': i = 1;break;
            case '-': i = 2;break;
            case '*': i = 3;break;
            case '/': i = 4;break;
            case '^': i = 5;break;
            case '(': i = 6;break;
        }
        switch(ch2){
            case '#': j = 0;break;
            case '+': j = 1;break;
            case '-': j = 2;break;
            case '*': j = 3;break;
            case '/': j = 4;break;
            case '^': j = 5;break;
            case '(': j = 6;break;
        }
        return rela[i][j];
    }
    
    
    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;
    }
    
    bool IsOperation(char ch){//判断是不是操作符 
        if(ch == '#' || ch == '+' || ch == '-' ||
           ch == '*' || ch == '/' || ch == '^' )
           return true;
           return false;
    }
    
    int ExpEvaluation(){//实现 
        LinkStack ovs, optr;
        InitStack(&ovs);
        InitStack(&optr);
        Push(optr, (int)'#');
        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 if(IsOperation(ch)){
                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;
                }
            }
            else if(ch == '('){//遇见左括号直接进OPTR栈 
                Push(optr, (int)ch);
                ch = getchar();
            }
            else if(ch == ')'){//遇见左括号 
                while((char)GetTop(optr) != '('){//直到栈顶元素为左括号结束本次循环 
                    Pop(optr, &op); //OPTR退栈一次 
                    Pop(ovs, &a);//OVS退栈两次 ,进行相应的计算,把结果压入OVS栈中 
                    Pop(ovs, &b);
                    t = Calculate(b, (char)op, a);
                    Push(ovs, t);
                }
                Pop(optr, &op);//弹出左括号操作 
                ch = getchar();
            }
        }
        t = GetTop(ovs);//取栈顶元素,返回最终计算结果 
        return t; 
    }
    
    int main(){
        printf("
    
    Please input an expression(Ending with '#'):
    ");
        int ans = ExpEvaluation();
        printf("%d
    ", ans);
        return 0;
    }

    运行结果:

    种一棵树最好的时间是十年前,其次是现在。
  • 相关阅读:
    java.lang.ArrayIndexOutOfBoundsException异常分析及解决
    Android_开发片段(Part 2)
    保存错误日志回传服务器之回传错误“信息文件”
    node.js
    拼接json
    CommonJS / Node.js/ Vue学习资料
    合并PDF
    java 多线程
    linux 运行jar包
    mvn 命令
  • 原文地址:https://www.cnblogs.com/HyattXia/p/9798208.html
Copyright © 2020-2023  润新知