本文介绍队列和栈的实际应用:括号匹配、表达式求值


一、括号匹配问题

【问题描述】:给定一个仅含有括号的字符串,如何去判断该括号序列是否合法呢?
例如:()()合法,(())合法,【()】合法
但((()不合法,【)【)不合法

用栈来解决。


下面开始模拟算法,走两遍


比如第一种情况:【()】【】

参考上面的算法思想,执行过程:
1、先看第一个括号,因为是左括号,所以直接把第一个括号【,压入栈中。
2、再看第二个,也是左括号(,所以直接扔进栈就行
3、第三个括号是右括号),所以我们要弹出一个栈顶元素 ( 进行匹配,发现两者正好匹配,然后继续。现在栈中就只有一个元素【了。
4、第四个括号是】,同上,因为是右括号,所以弹出栈顶元素,然后发现是匹配的。继续,现在栈中没有元素了。
5、第五个是左括号,入栈
6、第六个是右括号,同三,匹配。现在栈中又没有元素了
7、字符串读取完毕,且此时栈中为空,所以字符串是满足括号匹配的!


情况2、字符串:【()

执行过程:
1、第一个括号为左括号,直接入栈
2、第二个括号为左括号,直接入栈
3、第三个括号为),弹出栈顶元素(,并检查是否匹配,发现两者匹配,因此继续。现在栈中元素为【
4、字符串读取完毕,但栈不空,所以该括号字符串不满足括号匹配!


情况3、字符串:【(】【】

执行过程:
1、第一个括号为左括号,直接入栈
2、第二个括号为左括号,直接入栈
3、第三个括号为右括号,所以弹出栈顶元素(,检查发现(和】是不匹配的,因此算法直接return false。该字符串不匹配。


二、表达式求值

先介绍三种表达式:

那么复杂的表达式,如何完成中缀转前缀呢?

中缀转前缀

核心思想,比如(A+B)*C
我们先把括号内部优先级高的,A+B转成前缀:+AB
然后把(+AB) *C种的+AB看作一个数
因此,最后的转换结果是:
*+ABC


中缀转后缀


思路和转前缀一样


用栈实现的算法模拟:

我们以中缀转后缀为例子

执行过程:
1、检测到是左括号(,入栈
2、同上,左括号入栈
3、检测到是数字A,于是将其抄写下来,此时后缀表达式为:A
4、运算符+,根据规则c,运算符优先级是高于左括号的,直接入栈
5、然后检测到数字B,于是抄写下来,此时后缀表达式为:AB
6、遇到右括号了,注意规则b,我们将栈中的运算符全部弹出加入到表达式中,然后直到遇到左括号,将其删除。此时后缀表达式为:AB+。栈中此时为:(
7、遇到*,乘号优先级比括号高,直接压到栈里面。
8、遇到数字C,将其抄写下,此时后缀表达式为:AB+C
9、遇到右括号,将乘号弹出,此时后缀表达式为:AB+C*。并且根据规则b,还要将栈中的左括号删除。那么此时栈中就空了
10、遇到-,因为栈空,直接入栈,
11、遇到左括号,加入栈中
12、遇到数字E,抄写下来,此时后缀表达式为:AB+C*E
13、遇到减号-,因为栈顶是(,所以直接入栈,此时栈内为:- ( -
三个元素
14、遇到数字F,抄写,此时后缀表达式为:AB+C * EF
15、遇到右括号,将减号弹出,加入到表达式中,并且把左括号删除
此时后缀表达式为 AB+C * EF-
16、根据规则d,遍历完成,将栈中所有元素弹出,加入到表达式里。于是弹出减号,此时后缀表达式为 AB+C * EF–

得到最后的答案。

这个算法手动模拟起来稍微麻烦一点,大家多试试,弄熟就好了


后缀表达式求值

那么我们幸幸苦苦学会了中缀表达式转后缀表达式,到底是为了什么呢?相信很多读者看到这里都会有这样的疑问。哈哈,其实就是因为用后缀表达式来求值是一件非常简单的事情!而中缀表达式交给计算机去直接算,那可就麻烦了。

因此,我们回了中缀转后缀之后,就可以将复杂的中缀表达式先转成后缀表达式,然后再用后缀表达式的求值算法来计算出最后的值。

那,说了这么多,后缀表达式求值到底有多简单呢?

算法思想
利用一个栈,每次把操作数扔进栈,遇到一个运算符就把栈顶两个元素弹出做一个运算,然后再把运算结果压到栈中,循环以上过程,最后在栈里会得到一个数字,就是结果。

说的有点抽象,来个例子:
比如我们以上面那个后缀表达式为例子:
AB+C*EF–
比如我们取A = 3;B = 2;C = 2;E = 6;F = 4
那么根据其对应的中缀表达式【(A + B) * C】 - 【E - F】
我们可以算出,结果为8
下面我们用后缀表达式算法检验一下:

1、遇到数,无脑扔进栈。所以AB直接扔进,现在栈中元素:AB
2、遇到+,于是将栈顶两个元素AB弹出,做运算A+B = 3 + 2 = 5,将结果5压入栈
3、遇到C,直接入栈
4、遇到*,于是将C、5弹出,做运算C*5 = 5 * 2 = 10;将10压入栈
5、遇到E、F,直接无脑入栈,那么现在栈中:10, E, F三个元素
6、遇到-,将E、F弹出,做运算E - F = 6 - 4 = 2;将2压入栈
7、遇到-,将10、2弹出,做运算10 - 2 = 8。
8、字符串遍历完毕,栈中仅有的是结果,所以结果为8,经检验,算法正确!


所以今后做表达式求值算法的思路就很明确了,先将中缀表达式转后缀,然后再用后缀表达式求值算法求出结果即可。人比较擅长中缀表达式求值,但计算机更喜欢后缀表达式运算


【js代码实现】:
只针对+ - 的情况

 //中缀转后缀,然后后缀求值
var calculateBack = function(s){var stack = [];var arr = s.split("");for(let i = 0;i < arr.length;i++){if(arr[i] == '+' || arr[i] == '-')  continue;arr[i] = Number.parseInt(arr[i]);} for(let i = 0;i < arr.length;i++){ if(arr[i] == '+' || arr[i] == '-'){let x = stack[stack.length - 1];stack.pop();let y = stack[stack.length - 1];stack.pop();if(arr[i] == '+'){let val = x + y;stack.push(val);}else{let val = y-x;          //注意减法顺序不要反了stack.push(val);}}else{stack.push(arr[i]);}}return stack[0];
}//中缀转后缀
var midToBack = function(s){var res = [];var temp = s.trim().split("");var arr = [];for(let i = 0;i < temp.length;i++){if(temp[i] != ' '){arr.push(temp[i]);}} //下面为核心,上面都是预处理字符串var stack = [];for(let i = 0;i < arr.length;i++){if(arr[i] == '('){stack.push(arr[i]);}else if(arr[i] == ')'){while(stack[stack.length - 1] != '('){res.push(stack[stack.length - 1]);stack.pop()}stack.pop();}else if(arr[i] == '+' || arr[i] == '-'){if(stack.length != 0 && stack[stack.length - 1] != '('){while(stack.length != 0 && stack[stack.length - 1] != '('){res.push(stack[stack.length - 1]);stack.pop()}}stack.push(arr[i]);}else{res.push(arr[i]);}}//栈中剩余元素直接加过去while(stack.length != 0){res.push(stack[stack.length - 1]);stack.pop()} return res.join("");
}

数据结构之队列和栈的应用相关推荐

  1. 扑克牌游戏,两人接龙(数据结构:队列、栈、双向链表)

    游戏规则: 1.将一副牌中的大小王去掉,剩余的52张牌(1-13)*4,洗牌后按顺序分配给两名选手(这里用的方法是随机抽取其中的一张牌发给选手): 2.随机抽取其中一人先出牌,之后两人轮流将自己手里最 ...

  2. 银行业务队列简单模拟Java程序设计_PTA 数据结构 银行业务队列简单模拟

    仅供参考,请勿粘贴 设某银行有A.B两个业务窗口,且处理业务的速度不一样,其中A窗口处理速度是B窗口的2倍 -- 即当A窗口每处理完2个顾客时,B窗口处理完1个顾客.给定到达银行的顾客序列,请按业务完 ...

  3. 数据结构,堆和栈和队列的概念

    数据结构,堆和栈和队列的概念 1 什么是数据结构 数据结构是计算机存储,组织数据的反复改.数据结构是指相互之间存在的一种或多种特定关系的数据元素集合. 2 数据结构的逻辑结构 1 集合结构,元素都是孤 ...

  4. c语言用两个栈构造队列伪码,数据结构习题线性表栈队列.doc

    数据结构习题线性表栈队列 线性表(58) 1. 在单链表.双链表和单循环链表中,若仅知道指针p指向某结点,不知道头指针,能否将结点*p从相应的链表中删去?若可以,其时间复杂度各为多少? 2.设线性表的 ...

  5. 数据结构与算法(2)——栈和队列

    前言:题图无关,只是好看,接下来就来复习一下栈和队列的相关知识 前序文章: 数据结构与算法(1)--数组与链表(https://www.jianshu.com/p/7b93b3570875) 栈 什么 ...

  6. Java实现自定义队列和树结构_Java数据结构之链表、栈、队列、树的实现方法示例...

    本文实例讲述了java数据结构之链表.栈.队列.树的实现方法.分享给大家供大家参考,具体如下: 最近无意中翻到一本书,闲来无事写几行代码,实现几种常用的数据结构,以备后查. 一.线性表(链表) 1.节 ...

  7. 数据结构录 之 单调队列单调栈。

    队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...

  8. 数据结构与算法 | 用栈实现队列

    之前的几章我讲解了栈和队列的基本特性和一些基本的操作方法,那么如何能利用栈来实现队列呢? 下面我来讲解下具体思路,栈的特性先进后出,队列是先进先出,如果要模拟队列的这个特性,我们就必须用到两个栈. 一 ...

  9. 数据结构:线性数据结构(1)-栈(栈,队列,deques, 列表)

    栈,队列,deques, 列表是一类容器,他们数据项之间的顺序由添加或删除的顺序决定,一旦一个数据项被添加,它相对于前后元素一直保持该位置不变.注入此类的数据结构称为线性数据结构. 栈 栈(栈,队列, ...

  10. 数据结构与算法--利用栈实现队列

    利用栈实现队列 上一节中说明了栈的特点 后进先出,我们用数组的方式实现了栈的基本操作api,因此我们对栈的操作是不考虑排序的,每个api的操作基本都是O(1)的世界,因为不考虑顺序,所以找最大,最小值 ...

最新文章

  1. 20151102adonet2
  2. 年龄估计bridgeNet
  3. DropZone(文件上传插件)
  4. DM368开发 -- 常用指令演示
  5. 斐波那契数的两种求法(迭代,递归)
  6. 基于linux的智能小车_商汤首款原创机器人SenseRover X自动驾驶小车斩获Red Dot Award...
  7. 游族内部信:年终奖如期发放 继续招聘全球化游戏人才
  8. 考研计算机网络,2020计算机专业考研的计算机网络部分知识点
  9. bzoj千题计划277:bzoj4513: [Sdoi2016]储能表
  10. 【汇编语言与计算机系统结构笔记18】MIPS指令集与汇编程序设计 异常处理
  11. Zookeeper启动失败,报错 can not open chanel to 2
  12. mysql排序同值排名一致
  13. Unity3D(三)材质
  14. jQuery表格排序组件-tablesorter
  15. 【十次方】十次方项目介绍
  16. python词频统计排序小demo
  17. JavaWeb学习(较全较简)
  18. 天问:《三体》世界真的存在吗?(太阳系与银河系简介)
  19. 中国超级计算机之父 孟,晚霞未必逊晨曦——记“中国巨型计算机之父”金怡濂院士...
  20. “注释”是程序员的自我修养

热门文章

  1. 通过HOST VIP连接Oracle数据库
  2. Java面试题大全(part_4)
  3. 单片机中Code、RO、RW、ZI的含义即存储位置
  4. 电脑开机出现警报音后提示要按F1才能进入的分析处理
  5. 数学速算法_计算总是出算?小学数学常用的25种快速口算窍门,学好算数必备...
  6. 计算机中的原码、反码和补码计算
  7. 图卷积神经网络代码讲解,卷积神经网络python实例
  8. win7升级win10正式版_win7升级win10数据是否会丢失?
  9. 深度学习数据增强方法-内含(亮度增强,对比度增强,旋转图图像,翻转图像,仿射变化扩充图像,错切变化扩充图像,HSV数据增强)七种方式进行增强-每种扩充一张实现7倍扩)+ 图像缩放代码-批量
  10. YARN 作业执行流程