首页 > 编程语言 >算法-中缀转后缀表达式(C++)

算法-中缀转后缀表达式(C++)

时间:2024-10-16 17:22:07浏览次数:9  
标签:char 优先级 中缀 处理 后缀 elem C++ 运算符 括号

因为操作数在后缀表达式中它们的顺序与中缀表达式一致,所以操作数不需要进行特殊处理,所以遇到数字就输出,遇到符号就经过处理再输出

所以需要用一个存储结构存符号

为什么用栈存储:

要利用后进先出的特性

出栈也就是加入到后缀表达式中,一部分一部分处理,处理完一部分,要处理他邻近的那部分,也就是需要操作最近加入的运算符,而不是最开始加入的(那样离太远了),后进先出刚好符合

比如1+1+2*(3+5)-1/2

先处理括号内的这部分,处理完括号外的那部分,再处理*,后处理两个加号

处理符号概述:

从左至右依次遍历中缀表达式,一个字符一个字符的处理

运算符都要入栈处理,而后续输出的运算符也只从栈内取(保证取的运算符都是经过处理的)

(这里的栈内处理,实则不用在栈内操作运算符,而是通过于当前运算符做比较来当作处理)

什么时候输出:运算优先级较高时输出(因为要保证优先级高的先运算的原则)

(但由于输出的运算符只从栈内取,所以这里的输出具体来说是:运算优先级高于当前处理运算符时输出)

具体实现步骤:

因为:

括号内的运算符优先级最高,而左括号是运算括号内的起始标志,所以,一旦遇到左括号,需要存下,让括号内的运算符优先运算(也就说明了,左括号的优先级最低)

左括号消除标志是出现右括号

所以:

遇到左括号时,直接入栈,先存着

遇到右括号时,直接一直出栈,直到遇到左括号,把左括号也一并出栈

因为后缀表达式无括号这个运算符,所以只需要删除,不需要把括号放入后缀表达式

如果遇到其他运算符,

若栈空,则直接入栈

若栈非空:

1、如果当前运算符优先级高于栈顶运算符,则入栈

2、如果当前运算符优先级低于栈顶运算符,则将高于当前运算符的栈内元素全出栈,最后将当前运算符入栈

3、遍历完,把剩余栈内运算符全部输出

注意

不论前缀还是后缀表达式,都是从左至右运算,所以当遇到两个优先级相同的运算符时,先出现的运算符优先级高于后出现的,所以当前运算符优先级较低,这种情况归于1,用=来表示

代码

构造栈

#include <iostream>
#include<string>
using namespace std;
#define MAXQSIZE 100

typedef struct {
    char *base;  // 栈底指针
    char *top;   // 栈顶指针
    int stacksize;
} SqStack;

// 初始化栈
void InitStack(SqStack &S) {
    S.base = new char[MAXQSIZE];
    if (!S.base) {
        cout << "存储分配失败" << endl;
        return;
    }
    S.top = S.base;  // 栈顶指针初始化为栈底
    S.stacksize = MAXQSIZE;  // 设置栈的大小
}
// 判断栈空
bool isEmpty (SqStack &S)
{
    if (S.top == S.base) {
        return true;
    } 
    return false;
}

// 入栈
void Push(SqStack &S, char elem) {
    // 检查栈满
    if (S.top - S.base >= S.stacksize) {
        cout << "栈已满" << endl;
        return;
    } 
    *S.top++ = elem;  // 推入元素
}

// 出栈
void Pop(SqStack &S, char &elem) {
    if (!isEmpty(S)) {
        elem = *--S.top;
    } else {
        cout << "栈空,无法弹出元素。" << endl;
    }
}

// 获取栈顶元素
char getHead(SqStack &S) {

   return *(S.top - 1);

}

 预备函数

// 判断是否为运算符
bool isOperator(char elem) {
    return (elem == '+' || elem == '-' || elem == '*' || elem == '/' || elem == '(' || elem == ')');
}

// 得到优先级
int getPrecede(char elem) {
    if (elem == '(')
        return 0;
    if (elem == '+' || elem == '-')
        return 1;
    if (elem == '*' || elem == '/')
        return 2;
    return 0;
}

主要函数 

void transform(string expressions)
{
    // 用于存运算符
    SqStack S;
    InitStack(S);
    // 用于存出栈的元素
    char elem = '0';
    // 开始从左到右处理
    for (int i = 0; i < expressions.length(); i++)
    {
        char expression = expressions[i];
        if (expression == '(')
        {
            // 左括号直接入栈,优先级最低
            Push(S,expression);
        } else if (expression == ')')
        {
            // 右括号直接出栈直到遇到到左括号
            Pop(S,elem);
            while (elem != '(' && !isEmpty(S))
            {
                cout<<elem<<" ";
                Pop(S,elem);
            }
        } else {
            // 其他字符
            // 数字直接输出
            if (!isOperator(expression))
            {
                cout<<expression<<" ";
            } else {
                // 是运算符
                // 如果栈空,直接入栈
                if (isEmpty(S))
                {
                    Push(S,expression);
                    continue;
                }
                // 栈非空
                // 如果当前运算符优先级大于栈顶运算符,则入栈
                if (getPrecede(expression) > getPrecede(getHead(S)))
                {
                    Push(S,expression);
                } else {
                    // 当前运算符优先级低于栈顶运算符,一直输出,直到当前运算符优先级大于栈顶运算符,入栈
                    // 因为从左到右运算,所以先出现的运算符优先级高于后出现的,这里用“=”表示
                    while (getPrecede(expression) <= getPrecede(getHead(S)) && !isEmpty(S))
                    {
                        Pop(S,elem);
                        cout<<elem<<" ";
                    }
                    // 当前运算符优先级大于栈顶运算符,入栈
                    Push(S,expression);
                }
            }
        }
    }
    // 处理栈内剩余运算符
    while (!isEmpty(S))
    {
        Pop(S,elem);
        cout<<elem<<" ";
    }
}

测试

int main() 
{
    // 9+(3-1)*3+1/2
    // 9 3 1 - 3 * + 1 2 / +
    string expressions;
    cout<<"输入表达式"<<endl;
    cin>>expressions;
    cout<<"后缀表达式为:"<<endl;
    transform(expressions);
    return 0;
}

标签:char,优先级,中缀,处理,后缀,elem,C++,运算符,括号
From: https://blog.csdn.net/2301_80103773/article/details/142987224

相关文章

  • 打卡信奥刷题(056)用C++工具信奥P10566[普及组/提高] 「Daily OI Round 4」Analysis
    「DailyOIRound4」Analysis题目描述小C的信息技术老师给小C布置了一项作业,作业内容如下:有一个字符串,包含大小写字母和数字。你可以把任意一个字符变成另外一个字符,设变化之前字符的ASCII码为a......
  • C++构建工具-构建系统
    构建CI/CDCI这步,首先需要一个版本控制系统,当前最好用的就是git流程:主线分支上设置静态代码检查,用来检测每一笔提交的质量,比如命名规范等。 还会设置自动化单元测试,看守代码功能,并进行代码覆盖率分析代码拉取功能; 构建 安装包依赖项功能,依赖项需......
  • C++入门语法
    目录知识点补充1.C语言中的作用域作用域的种类作用域的影响2.以下是C++和C语言对全局变量和局部变量命名冲突的处理3.类型定义C++关键字命名空间1.C++提出的命名空间是为了解决C语言以下几个缺陷2.命名空间的3种定义方式2.1.正常的命名空间定义2.2.命名空间可以嵌......
  • C++ 排序算法(选择、冒泡、插入)
    八、选择排序(从小到大): 选择排序的基本思想是:每一趟从待排序的数据中,通过“打擂台”比较选出最小元素,放在这些数据的最前面。这样,第一趟把n个数中(第1个到第n个)最小的放在第一个位置,第二趟把剩余的n-1个数中(第2个到第n个)最小的放在第二个位置,第三趟把剩余的n......
  • 【数据结构】自己动手写一个C++链表功能
    链表数据结构在操作数据时具有更高的性能,但同时因为其结构的原因会造成时间复杂度为O(N),因此理解链表结构的底层实现能够让我们在开发中对程序的性能进行进一步优化。如果你不知道什么是链表或者时间复杂度,可以参考我另外两篇文章:【数据结构】数组、链表、堆栈、队列到......
  • c++面向对象的两种格式
            面向对象编程(OOP)是C++的一个重要特性,它允许你将代码组织成类(class)和对象(object),从而提高代码的可读性、可维护性和复用性。所以,在项目开发中使用面向对象编程是非常重要的,即便函数也可以提高封装性,但是,类的使用通俗来说,直接将函数封装,同时可以通过继承父类来大......
  • 南沙C++信奥赛陈老师解一本通题 1943:【08NOIP普及组】排座椅
    ​ 【题目描述】上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的DD对同学上课时会交头接耳。同学们在教室中坐成了MM行NN列,坐在第ii行第jj列的同学的位置是(i,ji,j......
  • 每日OJ题_牛客_礼物的最大价值_路径dp_C++_Java
    目录牛客_礼物的最大价值_路径dp题目解析C++代码Java代码牛客_礼物的最大价值_路径dp礼物的最大价值_牛客题霸_牛客网(nowcoder.com)描述:        在一个m×n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0)。你可以从棋盘的左上角开始拿格子......
  • 【C++】C++ STL 树形结构容器全解析:map、set、multimap、multiset 的使用与区别
    C++语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C++相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C++内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriority......
  • GESP2024年9月认证C++四级( 第一部分选择题(1-5))
    题三代码:#include<iostream>usingnamespacestd;//全局变量var,初始化为100intvar=100;//函数定义voidfunction(){//局部变量var,只在这个函数内部可见,初始化为200intvar=200;//输出局部变量var的值,即200......