逆波兰式

即我们平时所说的后缀表达式(将运算符写在操作数之后)

实现逆波兰式的算法,难度并不大,但为什么要将看似简单的中序表达式转换为复杂的逆波兰式?原因就在于这个简单是相对人类的思维结构来说的,对计算机而言中序表达式是非常复杂的结构。相对的,逆波兰式在计算机看来却是比较简单易懂的结构。因为计算机普遍采用的内存结构是栈式结构,它执行先进后出的顺序。

举个例子:
1+2就是一个中缀式,转换成后缀式为1 2 +
1+2*3…… ……1 2 3 * +
1+(2+5)…… ……1 2 5 + +
在计算这些表达式的值时,通过将数字入栈,遇到运算符后在把数字出栈,计算,计算完再次入栈。一直循环……
比如1 2 3 * +


通过以上实例,我们可以看到,计算机利用栈的性质计算后缀式的结果与我们人类用中缀式计算的结果并无差别。但是,我们不要忘了计算机的计算速度可是很快的,在进行一些比较复杂或是计算量较大的运算时,计算机可以迅速的得出答案,这样让计算机帮助我们去计算可以省下大量的时间何精力。
但前面也说了,计算机的思维方式和我们人的思维方式不同,计算机是硅基生物,而我们是碳生物。硅基生物虽然计算快我们比不上,但它不像我们碳基生物那么聪明,不懂得变通。因此,想让计算机帮我们计算,我们还需要把计算表达式转换成计算机看得懂的方式才行。

中缀转后缀

在中缀式中,有运算符的优先级以及括号的限制,因此,在计算的时候需要考虑计算先后的问题,但在后缀式中只有入栈与出栈的操作,因此,我们在中缀转后缀的时候需要提前把计算顺序考虑进去,以便于计算机可以直接运算。

比如:符号入栈

比如:符号出栈

比如:括号

代码

/* 判断优先级 --> 决定是否出入栈
** 符号优先级高于符号栈,如符号栈
** 符号优先级低于符号栈,符号栈里的符号出栈,入数字栈,继续向下比较
*/
bool IsPop(char a, char b)  //a为待比较符号,b为符号栈栈顶元素
{if (b == '(') return false;if (a == '*' || a == '/'){if (b == '+' || b == '-'){//可以如符号栈return false;}else{return true;}}//if (a == '+' || a == '-')//{//a符号为最低优先级,符号栈出栈return true;//}
}/* 中缀转后缀 src带入中缀式,des带出后缀式 */
void InfixToSuffix(char* src, char* des)
{/* 符号栈 */Stack symbol;symbol.data = (char*)malloc(strlen(src)/2);symbol.top = 0;int i = 0;int k = 0;while (src[i] != '\0'){/*----------- 特殊符号判断------------------------------*/if (src[i] == ' ')       //如果当前字符是空格,则往后走一个{i++;continue;}else if (src[i] == '(')   //左括号直接入栈{Push(&symbol, src[i]);}else if (src[i] == ')')    //遇到 ) ,输出( )之间的所有符号{while (Top(&symbol) != '('){des[k++] = Top(&symbol);des[k++] = ' ';Pop(&symbol);}Pop(&symbol);}/*----------------- 数字 -------------------------------*/else if (isdigit(src[i])){des[k++] = src[i];if (!isdigit(src[i + 1]))        //数字后加空格{des[k++] = ' ';}}/*----------------- 运算符 -------------------------------*/else{switch (src[i])        {case '+':case '-':case '*':case '/':if (Empty(&symbol))       //如果符号栈为空,直接入符号{Push(&symbol, src[i]);}else              //否则,判断是否选择入符号栈还是出栈顶元素{if (IsPop(src[i], Top(&symbol)))  //出符号栈{des[k++] = Top(&symbol);Pop(&symbol);continue;}else           //当前符号优先级高,入符号栈{Push(&symbol, src[i]);}}break;default:break;}}i++; /* 遍历下一字符 */}/*字符串已遍历完,把符号栈中剩余的符号入栈到数字栈中 */while (!Empty(&symbol)){des[k++] = Top(&symbol);des[k++] = ' ';Pop(&symbol);}des[k] = '\0';free(symbol.data);
}

当然,以上代码运行的条件是要有一个栈,栈的实现到没有多难,以下为栈的代码

Stack.h

#ifndef _STACK_H
#define _STACK_H#define ElemType char
#define MAXSIZE 20typedef struct _Stack
{ElemType *data;int top;        //栈顶指针(有效元素的个数)int size;
}Stack;/* 初始化 */
void Init_Stack(Stack* st);
/* 判空 */
bool Empty(Stack* st);
/* 入栈 */
void Push(Stack* st, ElemType val);
/* 出栈 */
ElemType Pop(Stack* st);
/* 获取栈顶元素 */
ElemType Top(Stack* st);#endif

Stack.cpp

#include <stdbool.h>
#include <malloc.h>
#include "Stack.h"/* 判满 */
static bool Full(Stack* st)
{return st->top == MAXSIZE;
}/* 判空 */
bool Empty(Stack* st)
{return st->top == 0;
}
/* 初始化 */
void Init_Stack(Stack* st)
{st->data = (ElemType*)malloc(sizeof(ElemType) * 20);st->size = MAXSIZE;st->top = 0;
}
/* 入栈 */
void Push(Stack* st, ElemType val)
{if (Full(st)) return;st->data[st->top++] = val;
}
/* 出栈 */
ElemType Pop(Stack* st)
{if (Empty(st)) return -1;st->top--;return st->data[st->top];
}
/* 获取栈顶元素 */
ElemType Top(Stack* st)
{if (Empty(st)) return -1;return st->data[st->top - 1];
}
测试

main.cpp

int main()
{char str[50] = "";printf("请输入表达式:");scanf("%[^\n]", str);        /* 输入字符串,以回车为结束标志*/char strRet[50] = "";      /* 接收中缀式转换成的后缀式 */InfixToSuffix(str, strRet);       /* 中缀转后缀 */printf("%s\n", strRet);            /* 输出后缀式*/return 0;
}

C++利用后缀转中缀(逆波兰算法)实现计算器

逆波兰算法(后缀表达式)相关推荐

  1. c语言数据结构逆波兰算法,[分享]表达式二叉树逆波兰式的转换程序源代码(C++)...

    [分享]表达式二叉树逆波兰式的转换程序源代码(C++) RT,这是我两年前学数据结构时的作品. 拿出来给大家分享. ps:当时才学C++,代码写的不好,见笑了./*将中缀式转换为表达式树,并打印逆波兰 ...

  2. java中缀表达式转后缀表达式(逆波兰算法)

    四则运算是栈的重要应用之一 中缀表达式转后缀表达式(逆波兰算法)过程 从左到右遍历中缀表达式 数字直接输出为后缀表达式一部分 如果是符号,则判断与栈顶元素的优先级 高于栈顶元素优先级直接入栈 低于或等 ...

  3. java实现逆波兰算法,【算法】逆波兰算法实现原理

    逆波兰算法介绍 假定给定一个只 包含 加.减.乘.除,和括号的算术表达式,你怎么编写程序计算出其结果. 问题是:在表达式中,括号,以及括号的多层嵌套 的使用,运算符的优先级不同等因素,使得一个算术表达 ...

  4. 关于逆波兰算法进行公式单位的推导

    关于逆波兰算法的链接如下逆波兰算法 原理:将一个长表达式转化为2个数字之间的运算. 需求:利用逆波兰算法,推导出一个字母长表达式的单位 import java.util.ArrayList; impo ...

  5. 波兰式、逆波兰式与表达式求值

    波兰式.逆波兰式与表达式求值 <数据结构>中关于栈的解释经常会涉及到逆波兰式,波兰式,中缀式表达式的求值问题.但是,十分惭愧,整个大一阶段, 数据结构的课程没有上够5节,没有意识要学习,吃 ...

  6. Python下基于栈和逆波兰算法实现四则运算

    参考<大话数据结构>一书4.9节,Python下基于栈和逆波兰算法实现四则运算. 栈的实现使用顺序结构,即基于列表实现,参考本人博客Python实现顺序结构栈Sequence Stack ...

  7. java实现逆波兰算法,基于逆波兰算法实现计算器(Java控制台版)

    前言 计算器是日常生活中很常见的工具之一,但并不意味着计算器的软件实现原理就很简单.不少初学的小伙伴在尝试开发计算器的功能时,受到算术表达式中运算符优先级和多层嵌套等问题的困扰.本文采用逆波兰算法来实 ...

  8. 逆波兰式数学表达式求解

    逆波兰式数学表达式求解 //输入逆波兰式表达式 #include<iostream> #include<string.h> using namespace std; //函数表 ...

  9. php逆波兰表达式,PHP逆波兰示意与表达式计算

    PHP逆波兰表示与表达式计算 ????? 说起表达式计算,想起一个笑话.我向他介绍,我们的PHP开发框架中有使用RPN对公式解析计算的类.于是,他笑我无知了.并且,还列出一系列的佐证,证明,在PHP中 ...

最新文章

  1. Datawhale入选DataFountain优秀组织
  2. linux 减少内存碎片,Linux的内存碎片
  3. 经典排序算法 - 冒泡和快排总结
  4. oracle 客户端访问数据库,ORACLE数据库客户端连接访问服务器
  5. 基于BPMN2.0的工单系统架构设计(上)
  6. 微信小程序服务器支付sdk,微信小程序之支付后如何调用SDK的异步通知
  7. java钟使用dwr_DWR中各种java方法的调用
  8. tcp压测工具_使用BeetleX的TcpBenchmark工具进行百万设备模拟测试
  9. C# 插入或删除word分页符
  10. Cannot create PoolableConnectionFactory (Communications link failure due to unde
  11. 2007年教育技术学专业硕士点招生简章
  12. 共享软件作者怎样才能月入万
  13. Python编程PTA题解大全——索引
  14. 39 Flutter仿京东商城项目 收货地址列表、增加 修改收货地址布局、弹出省市区选择器...
  15. 一篇文章认识《双目立体视觉》
  16. 【独立游戏】Sunset——二次元横版动作游戏
  17. 漫画 | 外行对程序员误会有多深!
  18. 超实用!如何让智能家居网络更安全?
  19. PostgreSQL修炼之道之PostgreSQL的核心架构(十一)
  20. kotlin 常用高阶函数

热门文章

  1. 文学类的小说,言情类的,没有排行榜上的
  2. 跨时钟域问题(CDC)
  3. 再次出发!FaceBook 开源“一站式服务“时序利器 Kats !
  4. 专题二 MATLAB矩阵处理
  5. Android关闭屏幕,但不休眠
  6. 解决外网与内网或内网之间的通信,NAT穿透
  7. 图像算法工程师 转行之路
  8. 国产FPGA市场格局及进展
  9. echarts 地图上如何打点
  10. NetFPGA-SUME10G以太网接口仿真问题