• 表达式求值(无括号)


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

    算法思想

    (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;
    }
    种一棵树最好的时间是十年前,其次是现在。
  • 相关阅读:
    iOS把经纬度反转为位置信息(街道名等)
    ubuntu+mongodb
    IE6下绝对定位的高度自适应
    用Waitn控制网页
    PHPCMS 模板修改
    ubuntu+apache2+mono+mvc3
    灵活强大的jquery分页,样式可自定义
    委托与事件概要笔记
    ubuntu+nodejs
    linux 学习day3
  • 原文地址:https://www.cnblogs.com/HyattXia/p/9784987.html
Copyright © 2020-2023  润新知