一、栈的理解


1. 栈的一个实际需求


QQ截图20200806110500.jpg
如计算一个数学表达式可以使用到栈。
**

2.栈的介绍(文字以及图示)

QQ截图20200806110555.jpg
QQ截图20200806110640.jpg

3. 栈的应用场景

QQ截图20200806110717.jpg


二、数组栈的实现

实现说明

QQ截图20200807111952.jpgQQ截图20200807112000.jpg

实现代码

源代码:**ArrayStackDemo.java**

说明:这里有判断栈已满、判断栈为空、入栈操作、出栈操作、遍历栈的多个方法。
判断栈已满:return top == maxSize-1;
判断栈为空:return top == -1;
入栈操作:判断栈是否满,top++;arrStack[top]=num;
出栈操作:判断栈是否为空,保存现有数据,top位置下移,进行返回
遍历栈:从上到下,top-0 进行遍历

  1. class ArrayStack{
  2. //设置栈的最大容量
  3. private int maxSize;
  4. //创建数组
  5. private int[] arrStack;
  6. //栈顶默认为-1
  7. private int top = -1;
  8. public ArrayStack(int maxSize) {
  9. //根据参数来开辟空间
  10. this.maxSize = maxSize;
  11. arrStack = new int[maxSize];
  12. }
  13. //判断栈是否已满
  14. public boolean isFull() {
  15. return top == maxSize-1;
  16. }
  17. //判断栈是否为空
  18. public boolean isEmpty() {
  19. return top == -1;
  20. }
  21. //进行入栈操作
  22. public void pushStack(int num) {
  23. //判断栈是否已满
  24. if(isFull()) {
  25. System.out.println("栈已满,无法入栈!");
  26. return;
  27. }
  28. //进行入栈操作
  29. arrStack[++top] = num;
  30. System.out.println("入栈成功");
  31. }
  32. //进行出栈操作
  33. public int popStack() {
  34. if(isEmpty()) {
  35. throw new RuntimeException("栈空,无法出栈!");
  36. }
  37. int value = arrStack[top];
  38. top--;
  39. return value;
  40. }
  41. //进行遍历栈
  42. public void showStack() {
  43. //判断栈是否为空
  44. if(isEmpty()) {
  45. System.out.println("栈为空无法遍历!");
  46. return;
  47. }
  48. System.out.println("栈从上至下结果:");
  49. for(int i=top;i>=0;i--) {
  50. System.out.println(arrStack[i]+" ");
  51. }
  52. }
  53. }

测试代码:(已测试,能够实现)

  1. package StackExer;
  2. import java.util.Scanner;
  3. public class ArrayStackDemo {
  4. public static void main(String[] args) {
  5. ArrayStack arrayStack = new ArrayStack(3);
  6. Scanner scanner = new Scanner(System.in);
  7. //用于接收进行的操作
  8. String str = new String();
  9. boolean flag = true;
  10. while(flag) {
  11. System.out.println("show :展示栈中数据");
  12. System.out.println("push :进行入栈操作");
  13. System.out.println("pop :进行出栈操作");
  14. System.out.println("exit :退出程序");
  15. System.out.println();
  16. System.out.println("请输入你想要进行的操作:");
  17. str = scanner.next();
  18. switch (str) {
  19. case "show"://遍历栈中的数据
  20. arrayStack.showStack();
  21. break;
  22. case "push"://进行入栈操作
  23. System.out.println("请输入您想要入栈的数字:");
  24. int num = scanner.nextInt();
  25. arrayStack.pushStack(num);
  26. break;
  27. case "pop"://进行出栈操作
  28. try {
  29. int value = arrayStack.popStack();
  30. System.out.println("出栈的数字为:" + value);
  31. } catch (Exception e) {
  32. System.out.println(e.getMessage());
  33. }
  34. break;
  35. case "exit":
  36. flag = false;
  37. break;
  38. }
  39. }
  40. }
  41. }

三、链表栈的实现

源代码:ListStackDemo.java

三步骤(创建节点+方法说明+测试)

首先创建栈的节点:

  1. //创建栈中的节点
  2. class Node{
  3. public int value;
  4. public Node next;
  5. public Node(int value) {
  6. this.value = value;
  7. }
  8. }

创建栈:使用链表实现
说明:包含了**判断栈是否为空、栈是否满、入栈操作、出栈操作、遍历栈、获取栈顶元素。

判断栈是否为空:return top==-1;
判断栈是否已满:return top == maxSize-1;

入栈操作:
① 判断栈是否已满
② 上移top,判断top是否为1,是的话创建栈底的元素bottomNode并赋值topNode;
不是第一次那么根据top来使用辅助节点进行上移节点到栈顶位置,temp.next = new Node(val),topNode = new Node(value);

出栈操作:
① 判断是否为空
② 使用辅助节点temp以及事先存储号topNode的值。
③ 使用辅助节点找到出栈节点的前一个,为栈顶元素赋值topNode = temp;,接着删除temp的下一个节点,temp.next=null,最后返回value

获取栈顶元素:return topNode.value

遍历操作:
根据top创建一维数组,遍历链表同时给数组赋值,最后根据top从后往前遍历数组输出即可。

  1. //创建管理栈的类
  2. class ListStack{
  3. //栈底节点
  4. private Node bottomNode;
  5. //栈顶节点
  6. private Node topNode;
  7. //栈的最大容量
  8. private int maxSize;
  9. //指向最高的位置
  10. private int top = -1;
  11. //构造器设置栈中的最大容量
  12. public ListStack(int maxSize) {
  13. this.maxSize = maxSize;
  14. }
  15. //判断栈为空
  16. public boolean isEmpty() {
  17. return top == -1;
  18. }
  19. //判断栈已满
  20. public boolean isFull() {
  21. return top == maxSize-1;
  22. }
  23. //进行入栈操作
  24. public void pushList(int value) {
  25. //判断栈是否已满
  26. if(isFull()) {
  27. System.out.printf("栈已满,无法入栈!\n\n");
  28. return;
  29. }
  30. top++;//首先上移top
  31. if(top == 0) {
  32. //创建栈底元素以及设置栈顶元素
  33. bottomNode = new Node(value);
  34. topNode = new Node(value);
  35. }else {
  36. //其他插入情况
  37. //使用辅助节点
  38. Node temp = bottomNode;
  39. for(int i=1;i<=top-1;i++) {
  40. temp = temp.next;//将辅助节点上移到插入元素之前
  41. }
  42. //进行入栈操作
  43. temp.next = new Node(value);
  44. //栈顶也要进行赋值
  45. topNode = new Node(value);
  46. }
  47. System.out.printf("%d入栈成功!\n\n",value);
  48. }
  49. //进行出栈操作
  50. public int popList() {
  51. //判断栈中数据是否为空
  52. if(isEmpty()) {
  53. throw new RuntimeException("栈中数据为空,无法出栈!");
  54. }
  55. //使用辅助节点
  56. Node temp = bottomNode;
  57. //变量保存最后栈中元素
  58. int value = topNode.value;
  59. //指向栈顶位置-1
  60. top--;
  61. //使temp到达出栈的前一个顶点
  62. for(int i=0;i<=top-1;i++) {
  63. temp = temp.next;
  64. }
  65. //更新栈顶元素
  66. topNode = temp;
  67. if(top==-1) {
  68. //出栈最后一个元素时
  69. bottomNode = null;
  70. topNode = null;
  71. }else {
  72. temp.next = null;//清除栈顶元素
  73. }
  74. return value;
  75. }
  76. //遍历栈
  77. public void showList() {
  78. //判断是否为空
  79. if(isEmpty()) {
  80. System.out.printf("栈中数据为空,无法遍历!\n\n");
  81. return;
  82. }
  83. //顶一个辅助节点
  84. Node temp = bottomNode;
  85. //创建一个数组
  86. int []arr = new int[top+1];
  87. for(int i=0;i<=top;i++) {
  88. arr[i] = temp.value;
  89. temp = temp.next;
  90. }
  91. //进行 反向打印数组的value值
  92. for(int i=top;i>=0;i--) {
  93. System.out.printf("a[%d]=%d ",i,arr[i]);
  94. }
  95. System.out.println();
  96. }
  97. //查看栈顶元素
  98. public int getTopNode() {
  99. //判断是否为空
  100. if(isEmpty()) {
  101. throw new RuntimeException("栈中数据为空,无法查看栈顶!");
  102. }
  103. return topNode.value;
  104. }
  105. }

测试代码:(已测试成功)

  1. package StackExer;
  2. import java.util.Scanner;
  3. public class ListStackDemo {
  4. public static void main(String[] args) {
  5. ListStack listStack = new ListStack(3);
  6. Scanner scanner = new Scanner(System.in);
  7. //用于接收进行的操作
  8. String str = new String();
  9. boolean flag = true;
  10. while(flag) {
  11. System.out.println("show :展示栈中数据");
  12. System.out.println("push :进行入栈操作");
  13. System.out.println("pop :进行出栈操作");
  14. System.out.println("get :获取栈顶元素");
  15. System.out.println("exit :退出程序");
  16. System.out.println();
  17. System.out.println("请输入你想要进行的操作:");
  18. str = scanner.next();
  19. switch (str) {
  20. case "show"://遍历栈中的数据
  21. listStack.showList();
  22. break;
  23. case "push"://进行入栈操作
  24. System.out.println("请输入您想要入栈的数字:");
  25. int num = scanner.nextInt();
  26. listStack.pushList(num);
  27. break;
  28. case "pop"://进行出栈操作
  29. try {
  30. int value = listStack.popList();
  31. System.out.println("出栈的数字为:" + value);
  32. } catch (Exception e) {
  33. System.out.println(e.getMessage());
  34. }
  35. break;
  36. case "exit":
  37. flag = false;
  38. break;
  39. case "get":
  40. try {
  41. int value = listStack.getTopNode();
  42. System.out.println("栈顶元素为:" + value);
  43. } catch (Exception e) {
  44. System.out.println(e.getMessage());
  45. }
  46. break;
  47. }
  48. }
  49. }
  50. }



**




**

四、栈实现综合计算器(中缀表达式) 实际应用


思路分析(题意+图解)

题意要求
QQ截图20200808152403.jpg

图解分析
QQ截图20200808152412.jpg

① 实现加减乘除(个位数运算+三部分实现)

源代码:Calculator.java

首先是数组栈的实现,增加获取栈顶元素值方法

  1. class ArrayStack2{
  2. //设置栈的最大容量
  3. private int maxSize;
  4. //创建数组
  5. private int[] arrStack;
  6. //栈顶默认为-1
  7. private int top = -1;
  8. public ArrayStack2(int maxSize) {
  9. //根据参数来开辟空间
  10. this.maxSize = maxSize;
  11. arrStack = new int[maxSize];
  12. }
  13. //判断栈是否已满
  14. public boolean isFull() {
  15. return top == maxSize-1;
  16. }
  17. //判断栈是否为空
  18. public boolean isEmpty() {
  19. return top == -1;
  20. }
  21. //进行入栈操作
  22. public void pushStack(int num) {
  23. //判断栈是否已满
  24. if(isFull()) {
  25. System.out.println("栈已满,无法入栈!");
  26. return;
  27. }
  28. //进行入栈操作
  29. arrStack[++top] = num;
  30. }
  31. //进行出栈操作
  32. public int popStack() {
  33. if(isEmpty()) {
  34. throw new RuntimeException("栈空,无法出栈!");
  35. }
  36. int value = arrStack[top];
  37. top--;
  38. return value;
  39. }
  40. //进行遍历栈
  41. public void showStack() {
  42. //判断栈是否为空
  43. if(isEmpty()) {
  44. System.out.println("栈为空无法遍历!");
  45. return;
  46. }
  47. System.out.println("栈从上至下结果:");
  48. for(int i=top;i>=0;i--) {
  49. System.out.println(arrStack[i]+" ");
  50. }
  51. }
  52. //获取栈顶元素
  53. public int getTopValue() {
  54. if(isEmpty()) {
  55. throw new RuntimeException("栈中为空,无法取出");
  56. }
  57. return arrStack[top];
  58. }
  59. }

创建一个工具类为之后调用更加简便

包含三个方法:
① 判断是运算符还是数字,返回true为运算符,false为数字
② 根据传入字符来返回优先等级用1,0表示,1表示* / 0为+-,1优先级更高 0优先级低
③ 传入两个数一个运算符,根据运算符进行运算,返回运算值

  1. class Utils{
  2. //判断是运算符还是数字
  3. public static boolean isOper(char ch) {
  4. return ch=='+' || ch=='*' || ch == '-' || ch=='/';
  5. }
  6. //给出优先级等级
  7. public static int priority(int ch) {
  8. if(ch == '*' || ch == '/') {
  9. return 1;
  10. }else if(ch == '+' || ch=='-') {
  11. return 0;
  12. }else {
  13. throw new RuntimeException("无法检测出优先等级");
  14. }
  15. }
  16. //根据运算符对两个数值进行运算
  17. public static int operatorNum(int num1,int num2,int oper) {
  18. int result = 0;
  19. switch (oper) {
  20. case '+':
  21. result = num1+num2;
  22. break;
  23. case '-':
  24. result = num1-num2;
  25. break;
  26. case '*':
  27. result = num1*num2;
  28. break;
  29. case '/':
  30. result = num1/num2;
  31. break;
  32. default:
  33. break;
  34. }
  35. return result;
  36. }
  37. }

实现计算器

前提准备:
使用两个栈,一个用来存放数字,一个用来存放运算符。
代码实现过程:
整体两个部分。
第一个部分是将对应表达式中数字以及运算符入栈,并且处理掉优先级高的运算符;
第二个部分就是处理剩下来优先级低的运算符,将所有运算符进行处理完,数字栈中最后只剩下一个数字那就是最后的结果。
更多细节部分查看上面的思路分析解决

  1. package StackExer;
  2. public class Calculator {
  3. public static void main(String[] args) {
  4. String str = "3*1+2*6-5";
  5. //对str进行入栈操作,并且入栈过程中将对应之前优先级高的进行处理
  6. int index = 0;//对应str的下标
  7. char ch = ' ';//用于取对应下标的字符
  8. //取出的两个数字
  9. int num1 = 0;
  10. int num2 = 0;
  11. int oper = 0;//栈中取出的运算符
  12. int result = 0;//算运算之和
  13. //创建两个栈,一个数字栈、一个存放运算符栈
  14. ArrayStack2 numStack = new ArrayStack2(10);
  15. ArrayStack2 charStack = new ArrayStack2(10);
  16. while(index<str.length()) {
  17. ch = str.charAt(index);
  18. //1.判断是数字还是运算符
  19. if(Utils.isOper(ch)) {
  20. //是运算符时
  21. //2.判断字符栈中是否为空
  22. if(charStack.isEmpty()) {
  23. //直接入栈
  24. charStack.pushStack(ch);
  25. }else {
  26. //字符栈中不为空,进行判断优先级
  27. //3.待插入运算符与已插入的运算符进行优先级比较
  28. if(Utils.priority(ch)<=Utils.priority(charStack.getTopValue())) {
  29. //取出字符栈中的运算符
  30. oper = charStack.popStack();
  31. //注意num值取出的顺序
  32. num2 = numStack.popStack();
  33. num1 = numStack.popStack();
  34. result = Utils.operatorNum(num1, num2, oper);
  35. //将求出结果的值入栈
  36. numStack.pushStack(result);
  37. //将优先级低的入栈
  38. charStack.pushStack(ch);
  39. }else {
  40. //直接将运算符入栈
  41. charStack.pushStack(ch);
  42. }
  43. }
  44. }else {
  45. //不是运算符
  46. numStack.pushStack(ch-'0');
  47. }
  48. index++;//向后移一位
  49. }
  50. //处理剩余优先级相同的
  51. while(true) {
  52. //当字符栈为空时,说明已经结束求值了
  53. if(charStack.isEmpty()) {
  54. break;
  55. }
  56. //取出字符栈中的运算符
  57. oper = charStack.popStack();
  58. //注意num值取出的顺序
  59. num2 = numStack.popStack();
  60. num1 = numStack.popStack();
  61. result = Utils.operatorNum(num1, num2, oper);
  62. numStack.pushStack(result);
  63. }
  64. result = numStack.popStack();
  65. System.out.println("表达式结果为:"+result);
  66. }
  67. }

② 解决①中只能计算个位数的加减乘除(可以多位数)

源代码:Calculator.java

修改过程

说明:修改位置是判断读取是数字时的操作,可以对数字进行拼接。
QQ截图20200809111120.jpg

  1. package StackExer;
  2. public class Calculator {
  3. public static void main(String[] args) {
  4. String str = "3*1+2*600-500";
  5. //对str进行入栈操作,并且入栈过程中将对应之前优先级高的进行处理
  6. int index = 0;//对应str的下标
  7. char ch = ' ';//用于取对应下标的字符
  8. //取出的两个数字
  9. int num1 = 0;
  10. int num2 = 0;
  11. int oper = 0;//栈中取出的运算符
  12. int result = 0;//算运算之和
  13. String keepNum = "";
  14. //创建两个栈,一个数字栈、一个存放运算符栈
  15. ArrayStack2 numStack = new ArrayStack2(10);
  16. ArrayStack2 charStack = new ArrayStack2(10);
  17. while(index<str.length()) {
  18. ch = str.charAt(index);
  19. //1.判断是数字还是运算符
  20. if(Utils.isOper(ch)) {
  21. //是运算符时
  22. //2.判断字符栈中是否为空
  23. if(charStack.isEmpty()) {
  24. //直接入栈
  25. charStack.pushStack(ch);
  26. }else {
  27. //字符栈中不为空,进行判断优先级
  28. //3.待插入运算符与已插入的运算符进行优先级比较
  29. if(Utils.priority(ch)<=Utils.priority(charStack.getTopValue())) {
  30. //取出字符栈中的运算符
  31. oper = charStack.popStack();
  32. //注意num值取出的顺序
  33. num2 = numStack.popStack();
  34. num1 = numStack.popStack();
  35. result = Utils.operatorNum(num1, num2, oper);
  36. //将求出结果的值入栈
  37. numStack.pushStack(result);
  38. //将优先级低的入栈
  39. charStack.pushStack(ch);
  40. }else {
  41. //直接将运算符入栈
  42. charStack.pushStack(ch);
  43. }
  44. }
  45. }else {
  46. //是数字
  47. //需要考虑多位数情况
  48. //判断是否为最后一位
  49. if(index == str.length()-1) {
  50. //直接入栈即可
  51. numStack.pushStack(ch-'0');
  52. }else {
  53. //判断下一个是否是运算符
  54. if(Utils.isOper(str.charAt(index+1))) {
  55. //是的话直接入栈
  56. numStack.pushStack(ch-'0');//直接入栈
  57. }else {
  58. // //不是进行拼接
  59. // keepNum = String.valueOf(ch);
  60. // index++;
  61. // keepNum += str.charAt(index);
  62. // //这里进行入栈
  63. // numStack.pushStack(Integer.valueOf(keepNum));
  64. //首先接收这个数字
  65. keepNum = String.valueOf(ch);
  66. //进行循环判断拼接数字(下一个不越界同时下一个是数字的情况执行)
  67. while((index+1 <= str.length()-1)&&!Utils.isOper(str.charAt(index+1))) {
  68. keepNum += str.charAt(index+1);
  69. index++;
  70. }
  71. //将组成的数字入栈
  72. numStack.pushStack(Integer.valueOf(keepNum));
  73. }
  74. }
  75. }
  76. keepNum = "";//将keepNum进行清空
  77. if(index == str.length()-1) {
  78. break;
  79. }
  80. index++;//向后移一位
  81. }
  82. //处理剩余优先级相同的
  83. while(true) {
  84. //当字符栈为空时,说明已经结束求值了
  85. if(charStack.isEmpty()) {
  86. break;
  87. }
  88. //取出字符栈中的运算符
  89. oper = charStack.popStack();
  90. //注意num值取出的顺序
  91. num2 = numStack.popStack();
  92. num1 = numStack.popStack();
  93. result = Utils.operatorNum(num1, num2, oper);
  94. numStack.pushStack(result);
  95. }
  96. result = numStack.popStack();
  97. System.out.println("表达式结果为:"+result);
  98. }
  99. }

运行结果:**计算成功**
QQ截图20200809111240.jpg


五、前缀、中缀、后缀表达式(逆波兰表达式) 概述

① 前缀表达式介绍

QQ截图20200809122259.jpg

  • 计算流程

QQ截图20200809122342.jpg

② 中缀表达式介绍

QQ截图20200809122532.jpg

③ 后缀表达式介绍

QQ截图20200809122602.jpg

  • 求值过程

QQ截图20200809122609.jpg


六 、逆波兰计算器分析与实现

总体源代码:ReversedPolish.java
测试代码:ConfixTest.java
**

① 分析说明(中缀表达式转后缀表达式)

例子说明:
QQ截图20200811102532.jpg
需要通过两个栈进行处理,但为了方便用于存储后缀表达式的栈使用list集合来进行处理
① s1作为栈用来存储运算符或()符号。
② s2由于存储后缀表达式进行出栈取出之后还要进行反转才能获得,所以我们使用list集合来替代。

需要两个方法:
方法一:将String字符串表达式转化为List集合。
方法二:将中缀表达式(list集合)转化为后缀表达式

方法二详细步骤:
首先遍历list获取String字符串item
① 如果item是数字,那么直接保存到s2(list)中。
② 如果item是(,直接保存到s1(栈)中。
③ 如果item是),那么不断出栈存放到s2(list)中,直到栈中的(前,最后将( 符号出栈。
④ 如果item是运算符的话,那么循环比较栈顶以及item的优先级,条件:栈中有内容以及栈中优先级比item优先级大的话,进行出栈放入s2(list)中,最后item放入到s2(list)中;如果item优先级比栈顶大的话直接将item放入s2(list)中。
⑤ 最后遍历完list之后,将栈中的运算符依次出栈到s2(list)集合中保存

代码实现

  1. package StackExer;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Stack;
  5. //逆波兰表达式计算器
  6. public class ReversedPolish {
  7. //中缀表达式转为后缀表达式的两个方法
  8. //① 中缀表达式(String字符串)转为list形式存储数字以及其他运算符
  9. public static List<String> toInfixExpressionList(String str) {
  10. //当不符合表达式时返回null值的list
  11. if(str == null || str == "" || str.length()==0) {
  12. return new ArrayList<>();
  13. }
  14. //创建一个list
  15. List<String> list = new ArrayList<>();
  16. int index = 0;
  17. char ch = 0;
  18. String s = "";
  19. do {
  20. ch = str.charAt(index);
  21. //判断为数字还是其他符号
  22. if(ch<48 || ch >57) {
  23. //是其他符号
  24. list.add(""+ch);
  25. index++;
  26. }else {
  27. s="";
  28. //首先进行拼接 有个位数或多位数的情况
  29. while(index<str.length() && str.charAt(index)>=48 && str.charAt(index)<=57) {
  30. s += str.charAt(index);
  31. index++;
  32. }
  33. list.add(s);
  34. }
  35. }while(index<str.length());
  36. return list;
  37. }
  38. //② 将中缀表达式(list存储)转为后缀表达式
  39. public static List<String> infixToSuffixExpression(List<String> list){
  40. //创建一个栈、一个list集合 栈用来存放运算符 集合的话用于存放后缀表达式
  41. Stack<String> stack = new Stack<>();
  42. List<String> SuffixList = new ArrayList<>();
  43. for(String item:list) {
  44. //如果是数字直接添加入集合
  45. if(item.matches("\\d+")) {
  46. SuffixList.add(item);
  47. }else if(item.equals("(")) {
  48. //如果是(,那么直接入栈
  49. stack.push(item);
  50. }else if(item.equals(")")) {
  51. //将栈中的运算符进行出栈直到(前都添加到list中
  52. while(!stack.peek().equals("(")) {
  53. SuffixList.add(stack.pop());
  54. }
  55. //将栈中(出栈
  56. stack.pop();
  57. }else {
  58. //剩下来的是优先级的问题
  59. //若是item比栈中的优先级小时出栈并添加到集合中
  60. while(stack.size()!=0&&Operation.getValue(stack.peek())>=Operation.getValue(item)) {
  61. //若栈中有(则不比较直接跳出while
  62. if(Operation.getValue(stack.peek()) == 0) {
  63. break;
  64. }
  65. //将栈中优先级比item大的出栈到list集合中
  66. SuffixList.add(stack.pop());
  67. }
  68. //将item放入list集合中
  69. stack.push(item);
  70. }
  71. }
  72. //最后还要将栈中的剩余的添加到list中
  73. while(stack.size()!=0) {
  74. SuffixList.add(stack.pop());
  75. }
  76. return SuffixList;
  77. }
  78. }
  79. class Operation{
  80. private static int ADD = 1;
  81. private static int SUB = 1;
  82. private static int MUL = 2;
  83. private static int DIV = 2;
  84. public static int getValue(String oper) {
  85. int result = 0;
  86. switch (oper) {
  87. case "+":
  88. result = ADD;
  89. break;
  90. case "-":
  91. result = SUB;
  92. break;
  93. case "*":
  94. result = MUL;
  95. break;
  96. case "/":
  97. result = DIV;
  98. break;
  99. default:
  100. break;
  101. }
  102. return result;
  103. }
  104. }

② 分析说明(后缀表达式求值)

源代码:ReversedPolish.java

QQ截图20200810145315.jpg
将中缀表达式转为后缀表达式:
(5+3)6+20 => 53+620+
(4+5)/3(3+2) => 45+3/32+

计算思路:
后缀表达式从左到右进行扫描,遇到数字进行入栈操作遇到运算符即出栈两次,后出栈数字 对先出栈数字进行运算再将结果入栈,重复操作指导扫描完整个表达式即可,最终栈中只会存在一个那就是结果

代码实现

需要两个方法:一个是将已编号的后缀表达式转为list集合方式存储;另一个则是进行计算。
这里只需要一个栈即可只用来存放对应数字,根据运算符进行出栈运算即可。

  1. package StackExer;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Stack;
  5. //逆波兰表达式计算器
  6. public class ReversedPolish {
  7. public static void main(String[] args) {
  8. // 首先写一个逆波兰表达式 (5+3)*12-20 => 76
  9. String str = "5 3 + 12 * 20 -";
  10. // 将String中的各个数转为List集合
  11. List<String> list = parseSuffixExpreesionList(str);
  12. System.out.println(list);
  13. int result = calcuate(list);
  14. System.out.println("最后运算结果为:" + result);
  15. }
  16. //后缀表达式相关的两个方法
  17. //① 将普通String类型转化为List类型
  18. public static List<String> parseSuffixExpreesionList(String str) {
  19. String[] strings = str.split(" ");
  20. //创建一个集合
  21. List<String> list = new ArrayList<>();
  22. for(String s:strings) {
  23. list.add(s);
  24. }
  25. return list;
  26. }
  27. //② 根据传入的list中进行计算
  28. public static int calcuate(List<String> list) {
  29. //创建一个栈
  30. Stack<String> stack = new Stack<>();
  31. int num1 = 0;
  32. int num2 = 0;
  33. int result = 0;
  34. //进行遍历
  35. for(String str:list) {
  36. if(str.matches("\\d+")) {
  37. //匹配1获取多位数字,直接入栈
  38. stack.push(str);
  39. }else {
  40. //从栈中取出两个数
  41. num2 = Integer.valueOf(stack.pop());
  42. num1 = Integer.valueOf(stack.pop());
  43. //获取到运算符 分别进行加减乘除
  44. if(str.equals("+")) {
  45. result = num1+num2;
  46. }else if(str.equals("-")) {
  47. result = num1-num2;
  48. }else if(str.equals("*")) {
  49. result = num1*num2;
  50. }else if(str.equals("/")) {
  51. result = num1/num2;
  52. }else {
  53. throw new RuntimeException("无法获取运算符进行运算!");
  54. }
  55. //还要将计算结果入栈
  56. stack.push(String.valueOf(result));
  57. }
  58. }
  59. //最后存在栈中的则是最后运算符结果
  60. return Integer.valueOf(stack.pop());
  61. }
  62. }

运行结果:
QQ截图20200810145930.jpg

总体测试(中缀->后缀->求解)

  1. package com.mjj.test;
  2. import java.util.List;
  3. import org.junit.Test;
  4. import StackExer.ReversedPolish;
  5. public class ConfixTest {
  6. @Test
  7. public void test() {
  8. String str = "1+((2+3)*40)-5";
  9. List<String> list = ReversedPolish.toInfixExpressionList(str);
  10. System.out.println("中缀表达式(list):"+list);//[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
  11. List<String> infixToSuffixExpression = ReversedPolish.infixToSuffixExpression(list);
  12. System.out.println("后缀表达式(list):"+infixToSuffixExpression);//[1,2,3,+,4,*,+,5,–]
  13. //[1, +, 2, +, 3, *, 4, -, 5]
  14. //通过后缀表达式来求得结果
  15. int result = ReversedPolish.calcuate(infixToSuffixExpression);
  16. System.out.println("Expression = "+result);
  17. }
  18. }

运行结果:
QQ截图20200811143029.jpg


七、逆波兰计算器完整版(参考)

功能说明

QQ截图20200811144128.jpg

源代码

ReversePolishMultiCalc.java


整理者:长路 时间:2020/8/6-2020/8/11