Java-数据结构-栈

栈的数据结构

栈是一种简单的数据存储结构,是一种特殊的线性表,与链表和顺序表一样,只是在数据的存储上不同,栈只允许从一端存储或取出元素,一般将存储或取出元素的一端称为栈顶,另一端不可操作,称为栈底,同时把存储元素称为入栈(push),取出元素称为出栈(pop),如果没有任何元素,称为空栈。
Java-数据结构-栈
从图中可以看到,入栈和出栈都是从栈顶操作,而栈顶指针总是指向第一个元素,因此可以看出栈的特点是FILO(First In Last Out)先进后出,栈的基本操作创建栈,判空,入栈,出栈,获取栈顶元素等,注意栈不支持对指定位置进行删除,插入。

栈的经典使用

符号匹配

编写程序的时候我们经常会用到括号()或者{},程序如何校验我们编写的程序是否少或者多了这种符号,或者个数正确的基础上检核是否匹配,如)(这种的就是不正确的,事实上,编译器也是借助于栈这种数据结构来对语法做检核的,比如下面的例子。
对字符串(str=”((5-3)*8-2)”)做语法检核
Java-数据结构-栈
检核流程如下:

  1. 从左到右依次对字符串str中的每个字符char进行语法检测,如果char是,左括号则入栈,如果char是右括号则出栈(有一对匹配就可以去匹配一个左括号,因此可以出栈),若此时出栈的字符char为左括号,则说明这一对括号匹配正常,如果此时栈为空或者出栈字符不为左括号,则表示缺少与char匹配的左括号,即目前不完整。
  2. 重复执行1操作,直到str检测结束,如果此时栈为空,则全部括号匹配,如果栈中还有左括号,是说明缺少右括号

表达式转换

我们知道人做计算的时候可以根据运算符的优先级选择先计算哪一部分的数据,比如1-2x3这种,我们能判断出先进行x计算,计算得出的值再做-操作,但是计算机并不能像人一样有判断能力,而且计算机只能识别高低电位两种标识,因此如果让计算机操作计算,就必须给出计算机能识别的操作表达式,这就引出了前缀表达式和后缀表达式。

前缀表达式(Prefix Notation)

是指将运算符写在前面,数字写在后面,不包含括号的表达式,为了纪念其发明者波兰数学家Jan Lukasiewicz所以前缀表达式也 叫做“波兰表达式”。比如 - 1 + 2 3。后缀表达式是从左向右解析,而前缀表达式是从右向左解析。

后缀表达式(Postfix Notation)

是指运算符写在操作数后面的不含括号的算术表达式,也叫做逆波兰表达式。比如1 2 3 + -。由于后缀表达式的运算符在两个操作数的后面,那么计算机在解析后缀表达式的时候,只需要从左向右扫描,也就是只需要向前扫描,而不用回头扫描,遇到运算符就将运算符放在前面两个操作符的中间(这里先不考虑乘方类似的单目运算),一直运算到最右边的运算符,那么就得出运算结果了。

中缀表达式(Infix Notation)

就是常用的将操作符放在操作数之间的表达式。与前缀和后缀不同的是,前缀和后缀没有表示出运算的优先级,如 1+3*2。

中缀表达式转为后缀表达式

转换流程

中缀转后缀的转换过程需要用到栈,这里我们假设栈A用于协助转换,并使用数组B用于存放转化后的后缀表达式具体过程如下:

  1. 如果遇到操作数,我们就直接将其放入数组B中。
  2. 如果遇到运算符,则我们将其放入到栈A中,遇到左括号时我们也将其放入栈A中。
  3. 如果遇到一个右括号,则将栈元素弹出,将弹出的运算符输出并存入数组B中直到遇到左括号为止。注意,左括号只弹出并不存入数组。
  4. 如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素存入数组B直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到” ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( “。
  5. 如果我们读到了输入的末尾,则将栈中所有元素依次弹出存入到数组B中。
  6. 到此中缀表达式转化为后缀表达式完成,数组存储的元素顺序就代表转化后的后缀表达式。

执行图示过程如下:
Java-数据结构-栈
简单分析一下流程:

  • 当遇到操作数时,直接存入数组B中
  • 当i=1时,此时运算符为+,直接入栈
  • 当i=3再遇到运算符*,由于栈内的运算符+优先级比*低,因此直接入栈
  • 当i=4时,遇到运算符’(‘,直接入栈
  • 当i=6时,遇运算符-,直接入栈
  • 当i=8时,遇’)’,-和’(‘直接出栈,其中运算符-存入后缀数组B中
  • 当i=9时,由于*优先级比+高,而+与+平级,因此和+出栈,存入数组B,而后面的+再入栈
  • 当i=10,结束,+直接出栈存入数组B,此时数组B的元素顺序即为1 3 9 2 - * + 9 +
计算机解析后缀表达式

Java-数据结构-栈
简单分析一下流程:

  • (1)读到1392时不做任何操作
  • (2)读到-时,将9和2取出做9-1操作,计算之后的值放入栈
  • (3)循环(1)
  • (4)读到乘号的时候,取出3和7做乘法,计算之后的值入栈
  • (5)循环(1)
  • (6)读到+号,1+21操作,值放入
  • (7)循环(1)
  • (8)+号,22+9
    此过程也是靠栈来完成,图如下
    Java-数据结构-栈

中缀表达式转为前缀表达式

参考文章

https://blog.csdn.net/javazejian/article/details/53362993
https://www.cnblogs.com/fuck1/p/5995857.html
https://www.cnblogs.com/ysocean/p/7910432.html