• 栈的应用-综合计数器的实现


    目录

    前言

    一、思路分析

    二、代码实现

    总结

    前言

    在实现综合计数器之前,大家应该先了解一下什么是前中后缀表达式

    前缀、中缀和后缀表达式是表示数学表达式的三种不同方式。

    1. 前缀表达式(也称为波兰式或前缀记法):操作符位于操作数之前。例如,"+ 2 3"表示加法操作,其中2和3是操作数。

    2. 中缀表达式:操作符位于操作数之间。这是我们通常使用的数学表达式表示方式。例如,"2 + 3"表示加法操作,其中2和3是操作数。

    3. 后缀表达式(也称为逆波兰式或后缀记法):操作符位于操作数之后。例如,"2 3 +"表示加法操作,其中2和3是操作数。

    这三种表达式都可以表示相同的数学运算,只是操作符和操作数的排列顺序不同。在计算机中,后缀表达式常用于数学表达式的求值,因为它可以通过使用栈来进行简单而高效的计算。

    本次实现综合计算器就是借助后缀表达式来实现,为了简单起见,我们并不加入()等的符号


    一、思路分析

    定义两个栈,一个栈为数栈(NumStack)用来存放数字,另一个栈为符号栈,用来存放符号

    1. 通过一个 index  值(索引),来遍历我们的表达式

    2. 如果我们发现是一个数字, 就直接入数栈

    3. 如果发现扫描到是一个符号,  就分如下情况

      3.1 如果发现当前的符号栈为 空,就直接入栈

      3.2 如果符号栈有操作符,就进行比较,果当前的操作符的优先级小于或者等于栈中的操作符, 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈, 果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.

    4. 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.

    5. 最后在数栈只有一个数字,就是表达式的结果

    我们来举个例子 图解 计算 7*2*2-5+1 = 24

    二、代码实现

    代码量太大,不可能一步一步解析了,上面的过程如果能看懂,并且编程有一定基础,下面代码应该不成问题,代码出处033_尚硅谷_栈实现综合计算器-思路分析(1)_哔哩哔哩_bilibili

    大家可以去看看

    1. package 逆波兰计数器;
    2. import StackDemo.StackEmptyException;
    3. import java.util.Arrays;
    4. import java.util.Scanner;
    5. class Test{
    6. public static void main(String[] args) {
    7. String str = "7*2*2-5+1";
    8. ArrayStack numStack = new ArrayStack(10);
    9. ArrayStack operaStack = new ArrayStack(10);
    10. String s = "";
    11. int nums1 = 0;
    12. int nums2 = 0;
    13. int index = 0;
    14. int opera = 0;
    15. char ch = ' ';
    16. while (true) {
    17. ch = str.charAt(index);
    18. // 判断该字符是否是符号
    19. if(operaStack.isOpera(ch)){
    20. // 判断符号栈是否为空
    21. if(!operaStack.isEmpty()){
    22. // 判断优先级
    23. if(operaStack.priority(ch) <= operaStack.priority(operaStack.peek())){
    24. nums1 = numStack.pop();
    25. nums2 = numStack.pop();
    26. opera = operaStack.pop();
    27. int cal = numStack.cal(nums1, nums2, opera);
    28. numStack.push(cal);
    29. operaStack.push(ch);
    30. }else{
    31. operaStack.push(ch);
    32. }
    33. }else{
    34. // 符号栈为空,直接入栈
    35. operaStack.push(ch);
    36. }
    37. }else{
    38. boolean flag = true;// 定义标志位 检查字符串是否达到末尾
    39. // 处理非个位数的情况 如 88 66 这样的数
    40. while (!operaStack.isOpera(ch)) {
    41. s+=ch;
    42. if(index == str.length() -1 ){
    43. numStack.push(Integer.parseInt(s));
    44. flag = false;
    45. break;
    46. }else {
    47. index++;
    48. ch = str.charAt(index);
    49. }
    50. }
    51. if(!flag){
    52. break;
    53. }
    54. numStack.push(Integer.parseInt(s));
    55. s = "";
    56. index--;
    57. }
    58. index++;
    59. if(index>=str.length()){
    60. break;
    61. }
    62. }
    63. while (true) {
    64. if(operaStack.isEmpty()){
    65. System.out.println(str+"="+numStack.pop());
    66. break;
    67. }
    68. nums1 = numStack.pop();
    69. nums2 = numStack.pop();
    70. opera = operaStack.pop();
    71. int cal = numStack.cal(nums1, nums2, opera);
    72. numStack.push(cal);
    73. }
    74. }
    75. }
    76. public class ArrayStack {
    77. private final int capacity;
    78. private int top = -1;
    79. private int[] stack ;
    80. public ArrayStack(int capacity){
    81. this.capacity = capacity;
    82. stack = new int[capacity];
    83. }
    84. // 入栈
    85. public void push(int data){
    86. if(isFull()){
    87. stack = Arrays.copyOf(stack,capacity*2);
    88. }
    89. top++;
    90. stack[top] = data;
    91. }
    92. // 出栈
    93. public int pop(){
    94. if(isEmpty()){
    95. throw new StackEmptyException("队列为空,无法删除元素");
    96. }
    97. int value = stack[top];
    98. top--;
    99. return value;
    100. }
    101. // 查看栈顶的值
    102. public int peek(){
    103. return stack[top];
    104. }
    105. // 制定优先级规则
    106. public int priority(int opera){
    107. if(opera == '*' || opera == '/'){
    108. return 1;
    109. }else if(opera == '+' || opera == '-'){
    110. return 0;
    111. }else{
    112. return -1;
    113. }
    114. }
    115. // 判断是否为运算符
    116. public boolean isOpera(int val){
    117. return val == '+' || val == '-' || val == '*' || val == '/';
    118. }
    119. // 运算方法
    120. public int cal(int num1,int num2,int opera){
    121. return switch (opera) {
    122. case '+' -> num1 + num2;
    123. case '-' -> num2 - num1;
    124. case '*' -> num1 * num2;
    125. case '/' -> num2 / num1;
    126. default -> -1;
    127. };
    128. }
    129. public boolean isFull(){
    130. return top == capacity - 1;
    131. }
    132. public boolean isEmpty(){
    133. return top == - 1;
    134. }
    135. }

    总结

    关于栈的应用远不止于此,大家也不必全部了解,只要能运用到这种程度,在刷点面试题,应付面试足矣!

  • 相关阅读:
    双倍数据速率I/O (ALTDDIO_IN、ALTDDIO_OUT)使用方法
    NOAUTH Authentication required. redis
    Springboot之拦截器Interceptor
    java教师教学质量评估系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    数据结构第三课 -----线性表之双向链表
    腾讯:《智能科技 跨界相变——2024数字科技前沿应用趋势》
    GCC 编译器
    入门力扣自学笔记72 C++ (题目编号515)
    OpenCV自学笔记十八:模板匹配
    linux文本排序统计、快捷键和通配符及引号
  • 原文地址:https://blog.csdn.net/weixin_73869209/article/details/132791952