如何利用栈解决问题。

Ref: 如何在程序中将中缀表达式转换为后缀表达式?

本文的引申:如何手写语法分析器

实现调度场算法

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”

规则:

从左到右遍历中缀表达式的每个数字和符号,

若是数字就输出,即成为后缀表达式的一部分;

若是符号,则判断其与栈顶符号的优先级,

是右括号或优先级低于栈顶符号(乘除优先加减)

    • 则栈顶元素依次出栈并输出,
    • 并将当前符号进栈,

一直到最终输出后缀表达式为止。

举个栗子:

1. 初始化一空栈,用来对符号进出栈使用。

2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”

3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。

4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”

5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -

6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”

7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +;然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。

8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”

9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2

10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+

“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”
 
从刚才的推导中你会发现,要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:
    1. 将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
    2. 将后缀表达式进行运算得出结果(栈用来进出运算的数字)。

整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。

Python 代码实践

import logging

class Stack:
def __init__(self):
self.items = [] def isEmpty(self):
return self.items == [] def push(self, item):
logging.info("Info: push {}".format(item))
self.items.append(item) def pop(self):
if True == self.isEmpty():
logging.info("Info: it's empty.")
return None
return self.items.pop() def peek(self):
if True == self.isEmpty():
logging.info("Info: it's empty.")
return None
return self.items[-1] def size(self):
return len(self.items) def __str__(self):
return "{}".format(self.items) logging.basicConfig(level=logging.INFO) # “9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+” def infixToPostfix(infixexpr):
prec = {}
prec["*"] = 3
prec["/"] = 3
prec["+"] = 2
prec["-"] = 2
prec["("] = 1
# 只有符号才需要“栈'
opStack = Stack()
postfixList = [] tokenList = infixexpr.split()
for token in tokenList:
if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "":
postfixList.append(token)
elif token == '(':
opStack.push(token)
elif token == ')':
# do...while, 把括号区间的符号都输出
while True:
topToken = opStack.pop()
if topToken == '(':
break
postfixList.append(topToken)
else:
# 因为符号只有两个优先级别,
# +来了,肯定弱于栈底元素;”先处理遗留问题”再入栈
# *来了,要么弱于栈底元素;要么更厉害,但反正还是要入栈
while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]):
# 这里就是“处理遗留问题”
postfixList.append(opStack.pop())
opStack.push(token) # “处理遗留问题”
while not opStack.isEmpty():
postfixList.append(opStack.pop()) return " ".join(postfixList)

print(infixToPostfix("A * B + C * D"))
print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )"))

End.

[LeetCode] 由 “中缀表达式 --> 后缀表达式" 所想的更多相关文章

  1. 栈的应用1——超级计算器(中缀与后缀表达式)C语言

    这里要学的程序主要用来实现一个功能——输入表达式输出结果,也就是一个计算器.效果如下: 这个程序主要有两个步骤:1.把中缀表达式转换为后缀表达式:2.计算后缀表达式的结果. 首先先明白几个问题: 1. ...

  2. Java数据结构和算法(六)——前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

  3. C++ 中缀转后缀表达式并求值

    //中缀转后缀 #include<iostream> #include<stack> using namespace std; int prio(char x){ ; ; ; ...

  4. Java数据结构和算法(六):前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

  5. 前缀、中缀、后缀表达式以及简单计算器的C++实现

    前缀表达式(波兰表达式).中缀表达式.后缀表达式(逆波兰表达式) 介绍 三种表达式都是四则运算的表达方式,用以四则运算表达式求值,即数学表达式的求解. 前缀表达式 前缀表达式是一种没有括号的算术表达式 ...

  6. 数据结构之栈—强大的四则复杂运算计算器(超过windows自带的科学计算器)【中缀转后缀表达式】

    比windows自带计算器还强的四则复杂运算计算器! 实测随机打出两组复杂算式:-7.5 * 6 / ( -2 + ( -6.5 -  -5.22 ) )与7.5+-3*8/(7+2) windows ...

  7. C++ 使用栈求解中缀、后缀表达式的值

    1. 前言 表达式求值对于有知识积累的你而言,可以通过认知,按运算符的优先级进行先后运算. 但对计算机而言,表达式仅是一串普通的信息而已,需要通过编码的方式告诉计算机运算法则,这个过程中栈起到了至关重 ...

  8. 前缀、中缀、后缀表达式及其相互转化的Java实现

    一.中缀表达式转换为前缀.后缀表达式 给个中缀表达式:a+b*c-(d+e)    首先根据运算符的优先级给所有运算单位加括号:((a+(b*c))-(d+e))    将运算符号移动到对应括号的前面 ...

  9. java四则运算----前缀、中缀、后缀表达式

    接到一个新需求,需要实现可配置公式,然后按公式实现四则运算. 刚拿到需求,第一反应就是用正则匹配‘(’,‘)’,‘+’,‘-’,‘*’,‘/’,来实现四则运算,感觉不复杂. 然后开始coding.发现 ...

随机推荐

  1. HBase 系列(八)——HBase 协处理器

    一.简述 在使用 HBase 时,如果你的数据量达到了数十亿行或数百万列,此时能否在查询中返回大量数据将受制于网络的带宽,即便网络状况允许,但是客户端的计算处理也未必能够满足要求.在这种情况下,协处理 ...

  2. SpringIoC和SpringMVC的快速入门

    更多内容,欢迎关注微信公众号:全菜工程师小辉~ Spring的优势? 降低了组件之间的耦合性 ,实现了软件各层之间的解耦 可以使用容易提供的众多服务,如事务管理,消息服务等 容器提供单例模式支持 容器 ...

  3. 在Keras中使用VGG进行物体识别(直接使用)

    https://blog.csdn.net/baimafujinji/article/details/80700263

  4. 【转】python爬虫之腾讯视频vip下载

    本文转自如下:作者:jia666666 原文:https://blog.csdn.net/jia666666/article/details/82466553 版权声明:本文为博主原创文章,转载请附上 ...

  5. RANSAC简史

    前言 在进行泡泡机器人[图灵智库]栏目的翻译的过程中,我发现在2018-2019的顶会中,依然有很多文章(我看到的不少于6篇)对RANSAC进行各种改进,这令我感到很吃惊.毕竟该方法在1981年就被提 ...

  6. python学习——python之禅

    (一)python之禅: 在python中运行import this你会看到这样一段文字: The Zen of Python, by Tim Peters   Beautiful is better ...

  7. ForkJoinPool 分支/合并框架

    ForkJoinPool 分支/合并框架 一.Fork/Join框架简介 Fork/Join 框架就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小 ...

  8. sql查询技巧指南

    传送门(牛客网我做过的每到题目答案以及解析) sql定义: 结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用 ...

  9. MySql优化相关概念的理解笔记

    MySQL架构 查询执行流程 查询执行的流程是怎样的: 连接1.1客户端发起一条Query请求,监听客户端的‘连接管理模块’接收请求1.2将请求转发到‘连接进/线程模块’1.3调用‘用户模块’来进行授 ...

  10. Python从入门到精通之环境搭建

    本章内容: Windows系统环境搭建 Linux系统环境搭建 Mac OS系统环境搭建 一.下载python安装包 下载地址:https://www.python.org/downloads/ 二. ...