数据结构 - 拓展突破(C++实现中缀表达式转前缀表达式,中缀表达式转后缀表达式,前缀表达式求值,中缀表达式求值)

1. C++中缀表达式转后缀表达式

输入中缀表达式样例:
2+48+(88+1)/3

输出后缀表达式样例:
248*+88*1+3/+

对于中缀表达式转换为后缀表达式,我们需要用以下步骤来解决这个问题:

  1. 初始化一个栈:运算符栈st
  2. 从左往右开始扫描中缀表达式
    • 遇到数字,直接输出
    • 遇到运算符:
      • 若为 ‘(’ 直接入栈
      • 若为 ‘)’ 将符号栈中的元素依次出栈并输出,直到 ‘(’, ‘(’ 只出栈,不输出
      • 若为其他符号,将符号栈中的元素依次出栈并将其输出,直到遇到比当前符号优先级更低的符号或者 ‘(’。
//首先定义优先级
#include <iostream>
#include <string>
#include <stack>

using namespace std;

int priority(const char ch)
{
    // */优先级相同最大
    int priority = 0;
    if (ch == '*' || ch == '/')
        priority = 2;
    else if (ch == '+' || ch == '-')
        priority = 1;
    else if (ch == '(')
        priority = 0;
    else
        //其他字符优先级错误
        priority = -1;
    return priority;
}

string turnPostfix(string &str)
{
    stack<char> st;
    string ret; //保存中缀转后缀的结果
    for (int i = 0; i < str.size(); i++)
    {
        // cout << str[i] << endl;

        //如果这个字符没有优先级,说明这个字符不是操作符
        if (priority(str[i]) == -1 && str[i] != ')')
        {
            //字符直接输出
            ret.push_back(str[i]);
        }
        else
        {
            if (st.empty())
            {
                st.push(str[i]);
            }
            else
            {
                //如果str[i]==)将栈输出,直到(
                if (str[i] == ')')
                {
                    while (st.top() != '(')
                    {
                        ret.push_back(st.top());
                        st.pop();
                    }
                    //将(弹出栈
                    st.pop();
                }
                else
                {
                    //如果是(直接入栈
                    if (str[i] == '(')
                    {
                        st.push(str[i]);
                    }
                    else
                    {
                        //将优先级大于这个操作符的字符出栈输出
                        //cout << "INFO:" << st.top() << endl;
                        while (!st.empty() && priority(st.top()) >= priority(str[i]))
                        {
                            ret.push_back(st.top());
                            st.pop();
                        }
                        //将这个操作符号入栈
                        st.push(str[i]);
                    }
                }
            }
        }
    }
    //将栈剩下的元素全部出栈
    while (!st.empty())
    {
        ret.push_back(st.top());
        st.pop();
    }
    return ret;//调用string的拷贝构造函数返回
}

int main()
{
    //string input = "2+4*8+(8*8+1)/3";
    string input = "a*(b+c)-d";
    cout << turnPostfix(input) << endl;
    return 0;
}

2. C++中缀表达式转前缀表达式

整体思路正好于后缀相反

输入中缀表达式:(a+b) * (c+d)

输出前缀表达式为: * ,+,a,b,+,c,d。

  1. 初始化一个运算符栈st

  2. 从右至左扫描中缀表达式,从右边第一个字符开始判断。

    • 遇到数字直接输出
    • 如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级则将运算符直接入栈;否则将栈顶运算符 出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级,再将这个运算符入栈(当栈顶是括号时,直接入栈)
      • 如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,并将左右括号删除
        -最后将字符串逆转就是前缀表达式
//首先定义优先级
#include <iostream>
#include <string>
#include <stack>
#include <algorithm>

using namespace std;

int priority(const char ch)
{
    // */优先级相同最大
    int priority = 0;
    if (ch == '*' || ch == '/')
        priority = 2;
    else if (ch == '+' || ch == '-')
        priority = 1;
    else if (ch == ')')
        priority = 0;
    else
        //其他字符优先级错误
        priority = -1;
    return priority;
}

string turnPrefix(const string &str)
{
    string ret;
    stack<char> st;
    for (int i = str.length() - 1; i >= 0; i--)
    {
        // cout << str[i] << " " << endl;
        if (priority(str[i]) == -1 && str[i] != '(')
        {
            //数字,直接输出到ret上即可
            ret.push_back(str[i]);
        }
        else
        {
            if (str[i] == '(')
            {
                //弹出栈,直到遇到)
                while (st.top() != ')')
                {
                    ret.push_back(st.top());
                    st.pop();
                }
                //将')'弹出栈
                st.pop();
            }
            else
            {
                if (st.empty())
                {
                    st.push(str[i]);
                }
                else
                {
                    if (str[i] == ')')
                    {
                        //右括号直接入栈
                        st.push(str[i]);
                    }
                    else
                    {
                        //栈优先级大的出栈
                        while (!st.empty() && priority(st.top()) > priority(str[i]))
                        {
                            ret.push_back(st.top());
                            st.pop();
                        }
                        //将这个操作符入栈
                        st.push(str[i]);
                    }
                }
            }
        }
    }
    while (!st.empty())
    {
        ret.push_back(st.top());
        st.pop();
    }

    std::reverse(ret.begin(), ret.end());
    return ret;
}

int main()
{
    string input = "1+((2+3)*4)-5";
    cout << turnPrefix(input) << endl;
    return 0;
}

3. C++后缀表达式求值

  1. 准备一个数字栈。从左到右扫描后缀表达式
  2. 如果是数字,放入数字栈。
  3. 如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将结果放进数字栈中。
  4. 如此反复,直到读完整个表达式后,留在数字栈中的那个数字就是最终结果。
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <functional>

using namespace std;

//传入后缀表达式
int PostfixToNumber(const string &str)
{
    std::map<char, std::function<int(int, int)>> opMap ={
            {'+', [](int x, int y){ return x + y; }},
            {'-', [](int x, int y){ return x - y; }},
            {'*', [](int x, int y){ return x * y; }},
            {'/', [](int x, int y){ return x / y; }},
    };

    stack<int> st;
    for (int i = 0; i < str.length(); i++)
    {
        if (str[i] >= '0' && str[i] <= '9')
        {
            st.push(str[i] - '0');
        }
        else
        {
            int right = st.top();
            st.pop();
            int left = st.top();
            st.pop();
            //实际上就是switch case 不同的运算符执行不同的运算,我这里使用C++11包装器
            st.push(opMap[str[i]](left,right));
        }
    }
    return st.top();
}

int main()
{
    //"2+4*8+(8*8+1)/3"
    cout<<PostfixToNumber("248*+88*1+3/+")<<endl;
}

4. C++前缀表达式求值

  1. 创建一个数字栈

  2. 从右至左扫描表达式,从右边第一个字符开始判断如果当前字符(或字符串)为数字或变量,则直接压入数字栈内;如果是运算符,则弹出两个数字运算;如此反复,直到读完整个表达式;

需要注意:

	后缀表达式右值为第一个栈顶元素,左值为第二个栈顶元素
	前缀左值为第一个栈顶元素,右值为第二个栈顶元素
#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <functional>

using namespace std;

//传入前缀表达式
int PrefixToNumber(const string &str)
{
    std::map<char, std::function<int(int, int)>> opMap ={
            {'+', [](int x, int y){ return x + y; }},
            {'-', [](int x, int y){ return x - y; }},
            {'*', [](int x, int y){ return x * y; }},
            {'/', [](int x, int y){ return x / y; }},
    };
    stack<int> st;
    for (int i = str.length() - 1; i >= 0; i--)
    {
        if (str[i] >= '0' && str[i] <= '9')
        {
            st.push(str[i] - '0');
        }
        else
        {
            int left = st.top();
            st.pop();
            int right = st.top();
            st.pop();
            st.push(opMap[str[i]](left,right));
        }
    }
    return st.top();
}

int main()
{
    //1+((2+3)*4)-5 
    cout<<PrefixToNumber("-+1*+2345")<<endl;
    return 0;
}

Github地址(2023考研数据结构实操,大题代码)

参考博客:

栈的应用之前、中、后缀表达式(C++)

前缀表达式和后缀表达式 - C++代码

【PTA】后缀表达式 (中缀表达式转化为后缀表达式)

  • 6
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现中缀表达式转后缀表达式前缀表达式的图形化界面,需要使用一些第三方库来实现界面设计和用户交互。下面以Qt为例,给出一个简单的实现过程: 1. 创建一个Qt项目并添加一个主窗口,用于显示图形界面。 2. 在主窗口上添加一些控件,如文本框、按钮等,用于输入中缀表达式、显示后缀表达式和前缀表达式等。 3. 在按钮的点击事件中编写代码实现中缀表达式转后缀表达式前缀表达式的功能。可以使用栈来实现换过程。 4. 将换后的后缀表达式和前缀表达式显示在相应的文本框中。 下面是一个简单的示例代码,用于实现中缀表达式转后缀表达式前缀表达式的图形化界面: ```cpp #include <QMainWindow> #include <QLineEdit> #include <QPushButton> #include <QLabel> #include <QHBoxLayout> #include <QStack> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 创建控件 infixEdit = new QLineEdit(this); postfixLabel = new QLabel(this); prefixLabel = new QLabel(this); convertBtn = new QPushButton("换", this); // 创建布局 QHBoxLayout *layout = new QHBoxLayout(); layout->addWidget(infixEdit); layout->addWidget(convertBtn); layout->addWidget(postfixLabel); layout->addWidget(prefixLabel); // 创建中缀表达式转后缀表达式前缀表达式的连接 connect(convertBtn, &QPushButton::clicked, this, &MainWindow::convert); // 设置布局 QWidget *widget = new QWidget(this); widget->setLayout(layout); setCentralWidget(widget); } public slots: void convert() { QString infix = infixEdit->text(); QString postfix = infixToPostfix(infix); QString prefix = infixToPrefix(infix); postfixLabel->setText(postfix); prefixLabel->setText(prefix); } private: QLineEdit *infixEdit; QLabel *postfixLabel; QLabel *prefixLabel; QPushButton *convertBtn; QString infixToPostfix(const QString &infix) { QStack<QChar> stack; QString postfix; for (int i = 0; i < infix.length(); i++) { QChar ch = infix[i]; if (ch.isDigit() || ch.isLetter()) { postfix += ch; } else if (ch == '(') { stack.push(ch); } else if (ch == ')') { while (!stack.isEmpty() && stack.top() != '(') { postfix += stack.pop(); } if (!stack.isEmpty() && stack.top() == '(') { stack.pop(); } } else { while (!stack.isEmpty() && precedence(stack.top()) >= precedence(ch)) { postfix += stack.pop(); } stack.push(ch); } } while (!stack.isEmpty()) { postfix += stack.pop(); } return postfix; } QString infixToPrefix(const QString &infix) { QString reversed = reverse(infix); QString postfix = infixToPostfix(reversed); QString prefix = reverse(postfix); return prefix; } int precedence(QChar op) { if (op == '+' || op == '-') { return 1; } else if (op == '*' || op == '/') { return 2; } return 0; } QString reverse(const QString &str) { QString reversed; for (int i = str.length() - 1; i >= 0; i--) { reversed += str[i]; } return reversed; } }; ``` 在上面的代码中,我们创建了一个MainWindow类,并在其中添加了一个用于输入中缀表达式的文本框、一个用于显示后缀表达式的标签、一个用于显示前缀表达式的标签和一个用于换的按钮。在按钮的点击事件中,我们调用了infixToPostfix()和infixToPrefix()函数,分别实现中缀表达式转后缀表达式前缀表达式的功能。其中,infixToPostfix()函数使用了栈来实现换过程,infixToPrefix()函数则先将中缀表达式,再调用infixToPostfix()函数,最后再将结果翻回去得到前缀表达式。 这样,我们就实现了一个简单的中缀表达式转后缀表达式前缀表达式的图形化界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NUC_Dodamce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值