数据结构(栈的补充二)

83 阅读3分钟

2.用栈实现表达式求值

  • 用栈求中缀表达式值(从左到右扫描,需要两个栈,一个存操作数s1;一个存运算符s2)

运算符大于栈顶优先级入栈,若是小于等于,则对s2不停地执行出栈操作,每出栈一个运算符就同时从s1出栈两个操作数,然后拿着两个操作数和刚才出栈的运算符进行一次运算。注意1:第一次出栈的操作数在右边,第二次出栈的操作数在左边。这两个操作数是配合刚才的运算符进行一次运算的,那这两个操作数肯定有一个左右关系,它们之间是运算符。注意2:第二次出栈的操作数在左边,第一次出栈的操作数在右边,中间计算结果入栈s1,刚才说的是多次对s2执行出栈操作,每出栈一个运算符就要做一次刚才描述的运算,并把结果重新压入s1栈,直到发现最新的栈顶元素的运算优先级小于刚才扫描到的那一个带入栈的运算符的时候,那就将此运算符入栈。如果遇到右括号,那就将s2栈从栈顶到左括号的所有元素都出栈,并对每一个出栈的运算符做一次刚才描述的计算,即先把计算的结果压入S1栈。若当整个中缀表达式都扫描完之后,s2中依然有运算符,那就把所有运算符都出栈,并对每一个出栈的运算符做一次运算,并把运算的结果压入s1栈中,最后在s1栈的栈底就是整个表达式的求值结果了。

int getPriority(char op) //判断优先级的函数
{
    if (op == '+' || op =='-')
        return 0; 
    else
        return 1;
}

int calSub(float opand1,char op, float opand2,float &result) //子表达式求值函数
{
    if(op == '+') result = opand1 + opand2;
    if(op == '-') result = opand1 - opand2;
    if(op == '*') result = opand1 * opand2;
    if(op =='/')
    {	
        if (fabs(opand2) <MIN) //求opand2的绝对值,用于检测除数是否为0
        {
            return 0; 
        }
        else
        {
            result = opand1 / opand2;
        }
    }
    return 1;
}


float calInfix(char exp[]) //求解中缀表达式的函数
{
    float s1[maxSize]; int top1 = -1; 
    char s2 [maxSize]; int top2= -1; 
    int i=0;
    while (exp[i] != '\0') //串没了就截至
    {
        if ('0' <= exp[i] && exp[i] <= '9')
        {
            s1[++top1] = exp[i] - '0'; //字符ASCII转化成数字
            ++i;
        }
        else if (exp[i] == '(' )
        {
            s2[++top2] = '(';
            ++i;
        }
        else if (exp[i]	=='+'||
                 exp[i]	=='-'||	
                 exp[i]== '*'||
                 exp[i] == '/') 
        {
            if (top2 == -1 ||
                s2[top2] == '('||
                getPriority(exp[i])> getPriority(s2[top2]))
            {
                s2[++top2]	= exp[i];	
                ++i;
            }
            else
            {
                float opnd1,opnd2,result; 
                char op; 
                int flag;
                opnd2 = s1[top1--];
                opnd1 = s1[top1--];
                op=s2[top2--];
                flag = calSub(opnd1,op,opnd2,result);
                if (flag == 0)
                {
                    std::cout<<"ERROR"<<std::endl; //puts("ERROR"); 
                    break;
                }
                s1[++top1] = result;
             }   
        }            
        else if(exp[i]== ')')
        {
            while (s2[top2] != '(')
            {
                float opnd1, opnd2, result; 
                char op; 
                int flag;
                opnd2 = s1[top1--];
                opnd1 = s1[top1--];
                op=s2[top2--];
                flag = calSub(opnd1,op,opnd2,result); 
                if (flag == 0)
                {
                    std::cout<<"ERROR"<<std::endl; //puts("ERROR"); 
                    return 0;
                }
                s1[++top1] = result;
            }
            --top2;
            ++i;
        }
    }   
    while (top2 != -1)
    {
        float opnd1,opnd2,result; 
        char op;
        int flag;
        opnd2 = s1[top1--];
        opnd1 = s1[top1--];
        flag = calSub(opnd1,op,opnd2,result); 
        if (flag == 0)
        {
            std::cout<<"ERROR"<<std::endl; //puts("ERROR"); 
            return 0;
        }
        s1[++top1] = result;
    }
    return s1[top1];
}