表达式求值(栈)

关于栈

本周系统的学习了栈, 关于栈, 我看过一个很形象的描述, 有一群人被追到一个窄巷子里, 这个窄巷子只能允许一人通过, 里面的人要想出来, 必须后面的人先出来, 即遵循先入后出的规则, 这就是栈,类似的概念还有队列,他遵循先入先出的规则, 这里不多做介绍。

表达式求值

首先是表达式求值中要用到的栈的基本操作

  • 创建一个链栈, 包含数据和下一个元素地址
typedef struct LinkList
{
    char operatorAndData;
    struct LinkList *next;
}LinkList,*LinkNode;
  • 栈的基本属性, 包括栈顶和元素个数
typedef struct LinkStact
{
    LinkNode top;
    int count;
}LinkStack;
  • 创建链栈(栈是一个没有头结点的单链表)
State createStack(LinkStack *S) {
    S->count = -1;
    S->top = NULL;
    return OK;
}
  • 入栈操作(push)
State pushStack(LinkStack *S, char data) {
    LinkNode s;
    s = (LinkNode)malloc(sizeof(LinkList));
    s->operatorAndData = data;
    s->next = S->top;
    S->top = s;
    S->count++;
    return OK;
}
  • 出栈操作(pop)
State popStack(LinkStack *S,char *data) {
    LinkNode p;
    //判断栈空
    if (S->top == NULL || S->count==-1) {
        return ERROR;
    }
    *data = S->top->operatorAndData;
    p = S->top;
    S->top = S->top->next;
    S->count--;
    free(p);
    return OK;
}

主函数中进行的操作, 包括表达式的输入, 中缀转后缀操作等

  • 中缀转后缀
    while (inExpression[i]!='\0') {
        if (inExpression[i]<48 || inExpression[i]>57) {
            if (inExpression[i] == 41) {
                if (!(infixExpression.count < 0)) {
                    popStack(&infixExpression, &postTmp);
                    while (postTmp != 40) {
                        postfixExpression[j++] = postTmp;
                        if (!(infixExpression.count < 0))
                            popStack(&infixExpression, &postTmp);
                        else
                            break;
                    }
                }
            }
            else if (inExpression[i] == 43 || inExpression[i] == 45 ) {
                if (!(infixExpression.count < 0)) {
                    popStack(&infixExpression, &postTmp);
                    while (postTmp == 42 || postTmp == 47) {
                        postfixExpression[j++] = postTmp;
                        if (!(infixExpression.count < 0)) {
                            popStack(&infixExpression, &postTmp);
                        }
                        else
                            break;
                    }
                    pushStack(&infixExpression, postTmp);
                }
                pushStack(&infixExpression, inExpression[i]);
            }
            else {
                pushStack(&infixExpression, inExpression[i]);
            }
            
        }
        else {
            postfixExpression[j++] = inExpression[i];
        }
        i++;
    }
    while (!(infixExpression.count < 0)) {
        popStack(&infixExpression, &postTmp);
        postfixExpression[j++] = postTmp;
    }
  • 转化完成后, 求值
 //计算后缀表达式
 i = 0;
 while (i != j) {
     if (postfixExpression[i]<48 || postfixExpression[i]>57) {
         popStack(&computeStack, &operatorData1);
         popStack(&computeStack, &operatorData2);
         if (postfixExpression[i] == 43) {
             postTmp = (operatorData2-48 + operatorData1-48)+48;
             pushStack(&computeStack, postTmp);
         }
         
         if (postfixExpression[i] == 45) {
             postTmp = (operatorData2 - 48) -
             (operatorData1 - 48) + 48;
             pushStack(&computeStack, postTmp);
         }
         if (postfixExpression[i] == 42){
             postTmp = (operatorData2 - 48) *
             (operatorData1 - 48) + 48;
             pushStack(&computeStack, postTmp);
         }
         if (postfixExpression[i] == 47) {
             postTmp = (operatorData2 - 48) /
             (operatorData1 - 48) + 48;
             pushStack(&computeStack, postTmp);
         }
         
     }
     else
         pushStack(&computeStack, postfixExpression[i]);
     i++;
 }
 popStack(&computeStack, &result);
 printf("%c\n", result);
 return OK;
}

关于中缀转后缀

中缀转后缀是表达式求值的一种算法, 为了把人能看懂的语言转化为机器能看懂的语言, 然后写算法, 让机器运算。
遵循的规则
  1. 遇到操作数:添加到后缀表达式中或直接输出
  2. 栈空时:遇到运算符,直接入栈
    遇到左括号:将其入栈
    遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
    注意:左括号不输出到后缀表达式
  3. 遇到其他运算符:弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈
  4. 将栈中剩余内容依次弹出后缀表达式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值