栈在表达式求值中的应用优化——使用栈C/C++实现

栈在表达式求值中的应用优化

Tip

读者朋友你好,本篇文章的理论部分放在我的上一篇文章啦。

优化方法

上一篇文章中使用了队列,但是这多了一部分的内存开销,这篇文章我们将对上一篇文章的代码进行优化,使用两个栈(操作数栈和操作符栈)实现表达式求值。
唯一的不同在于,上一篇文章中操作符出栈是加入后缀表达式队列,但是在这次的代码实现中,操作符出栈,就会弹出操作数栈中的两个数进行运算结果再压回操作数栈,最后的操作数栈中剩余的将是运算结果。

Demo

#include <iostream>
#include <string>

using namespace std;

typedef struct NumNode {//操作数栈节点
    double data;
    NumNode *next;
} NumNode, *NumStack;

bool InitNumStack(NumStack &NS) {//初始化操作数占
    NumNode *s;
    s = (NumNode *) malloc(sizeof(NumNode));
    if (s == NULL)
        return false;
    s->next = NULL;
    NS = s;
    return true;
}

bool NumStackEmpty(NumStack &NS) {//操作数栈判空
    return NS->next == NULL;
}

bool NumPush(NumStack &NS, double num) {//操作数栈压栈
    NumNode *p;
    p = (NumNode *) malloc(sizeof(NumNode));
    if (p == NULL)
        return false;
    p->data = num;
    p->next = NS->next;
    NS->next = p;
    return true;
}

bool NumPop(NumStack &NS, double &num) {//操作数栈弹栈
    if (NumStackEmpty(NS))
        return false;
    NumNode *p;
    p = NS->next;
    num = p->data;
    NS->next = p->next;
    free(p);
    return true;
}

typedef struct OpNode {//操作符栈节点
    char data;
    OpNode *next;
} OpNode, *OpStack;

bool InitOpStack(OpStack &O) {//初始化操作符栈
    OpNode *s;
    s = (OpNode *) malloc(sizeof(OpNode));
    if (s == NULL)
        return false;
    s->next = NULL;
    O = s;
    return true;
}

bool OpStackEmpty(OpStack O) {//操作符栈判空
    return O->next == NULL;
}

bool OpPush(OpStack &O, char op) {//操作符栈压栈
    OpNode *p;
    p = (OpNode *) malloc(sizeof(OpNode));
    if (p == NULL)
        return false;
    p->data = op;
    p->next = O->next;
    O->next = p;
    return true;
}

bool OpPop(OpStack &O, char &elem) {//操作符栈弹栈
    if (OpStackEmpty(O))
        return false;
    OpNode *p;
    p = O->next;
    elem = p->data;
    O->next = p->next;
    free(p);
    return true;
}

bool OpGetTop(OpStack &O, char &elem) {//获取操作符栈顶部操作符
    if (OpStackEmpty(O))
        return false;
    OpNode *p;
    p = O->next;
    elem = p->data;
    return true;
}

char OpGetTopJudgment(OpStack &O) {//获取操作符栈顶部元素
    if (OpStackEmpty(O))
        return false;
    OpNode *p;
    p = O->next;
    char elem;
    elem = p->data;
    return elem;
}

bool RankNotLowerthanOp(OpStack &O, char &op) {//获操作符等级如果大于操作符站内元素
    char optop;
    OpGetTop(O, optop);
    cout << "********" << endl;
    cout << "@@@@" << op << "@@@" << optop << endl;
    if (optop == '(') {
        cout << "遇到未闭合(等待)的出现" << op << "入栈" << endl;
        return false;
    } else if (OpStackEmpty(O)) {
        cout << "操作栈空" << op << "入栈" << endl;
        return false;
    } else if (optop == '*' && op == '+') {
        cout << "当前为+栈顶为*出栈并入队" << endl;
        return true;
    } else if (optop == '/' && op == '+') {
        cout << "当前为+栈顶为/出栈并入队" << endl;
        return true;
    } else if (optop == '-' && op == '+') {
        cout << "当前为+栈顶为-出栈并入队" << endl;
        return true;
    } else if (optop == '*' && op == '-') {
        cout << "当前为-栈顶为*出栈并入队" << endl;
        return true;
    } else if (optop == '/' && op == '-') {
        cout << "当前为-栈顶为/出栈并入队" << endl;
        return true;
    } else if (optop == '+' && op == '-') {
        cout << "当前为-栈顶为+出栈并入队" << endl;
        return true;
    } else if (optop == '*' && op == '*') {
        cout << "当前为*栈顶为*出栈并入队" << endl;
        return true;
    } else if (optop == '/' && op == '*') {
        cout << "当前为/栈顶为/出栈并入队" << endl;
        return true;
    } else if (optop == '*' && op == '/') {
        cout << "当前为/栈顶为*出栈并入队" << endl;
        return true;
    } else {
        cout << "当前为/栈顶为/出栈并入队" << endl;
        return optop == '/' && op == '/';
    }
}


void countNum(string str, int length) {//计算过程
    NumStack N;
    InitNumStack(N);

    OpStack O;
    InitOpStack(O);

    for (int i = 0; i < length; i++) {
        if (48 <= (int) str[i] && (int) str[i] <= 57) {
            cout << "读到" << (int) str[i] - 48 << "入操作数栈" << endl;
            int num;
            num = (int) str[i] - 48;
            NumPush(N, num);
        } else if (str[i] == '(') {
            cout << "读到(" << "入栈" << endl;
            OpPush(O, str[i]);
        } else if (str[i] == ')') {
            cout << "读到)" << endl;
            while (!OpStackEmpty(O)) {
                char op;
                OpPop(O, op);
                cout << "$$$$" << op << "$$$$$$" << endl;
                if (op == '(') {
                    cout << "弹出并抛弃栈中(" << endl;
                    break;
                }
                cout << ")前" << op << "出栈并计算数栈顶两个数字" << endl;
                double a, b, c;
                NumPop(N, b);
                NumPop(N, a);
                if (op == '+') {
                    c = a + b;
                } else if (op == '-') {
                    c = a - b;
                } else if (op == '*') {
                    c = a * b;
                } else {
                    c = a / b;
                }
                NumPush(N, c);
            }
        } else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
            if (str[i] == '+') {
                cout << "读到+" << endl;
            } else if (str[i] == '-') {
                cout << "读到-" << endl;
            } else if (str[i] == '*') {
                cout << "读到*" << endl;
            } else if (str[i] == '/') {
                cout << "读到/" << endl;
            }


            while (RankNotLowerthanOp(O, str[i])) {
                char op;
                OpPop(O, op);
                cout << "比" << str[i] << "优先级高的" << op << "出栈并计算数栈顶两个数字" << endl;
                double a, b, c;
                NumPop(N, b);
                NumPop(N, a);
                if (op == '+') {
                    c = a + b;
                } else if (op == '-') {
                    c = a - b;
                } else if (op == '*') {
                    c = a * b;
                } else {
                    c = a / b;
                }
                NumPush(N, c);
            }
            OpPush(O, str[i]);
        }
    }

    while (!OpStackEmpty(O)) {
        char op;
        OpPop(O, op);
        double a, b, c;
        NumPop(N, b);
        NumPop(N, a);
        if (op == '+') {
            c = a + b;
        } else if (op == '-') {
            c = a - b;
        } else if (op == '*') {
            c = a * b;
        } else {
            c = a / b;
        }
        NumPush(N, c);
    }

    double resule;
    NumPop(N, resule);
    cout << "结果为" << resule << endl;

}

int main() {
    string str;
    cin >> str;
    int length = str.size();
    countNum(str, length);
    return 0;
}

运行结果

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值