• 中缀表达式 - 栈实现综合计算器


    代码: 

    1. package Algotithm.stack
    2. object Calculator {
    3. def main(args: Array[String]): Unit = {
    4. val expression = "3+2*6-2"
    5. //创建两个栈:数栈、符号栈
    6. val numStack, operStack = new ArrayStack2(10)
    7. //定义需要的相关变量
    8. var index, num1, num2, oper, res = 0 //用于扫描
    9. var ch: Char = ' ' //每次扫描得到的char保存到ch
    10. var keepNum: String = ""
    11. //开始循环扫描入栈
    12. while (index < expression.length) {
    13. ch = expression.charAt(index)
    14. //判断是什么
    15. if (operStack.isOper(ch)) {
    16. if (operStack.isEmpty) {
    17. //如果为空直接入栈
    18. operStack.push(ch)
    19. } else {
    20. //如果不为空
    21. if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
    22. //从数栈中pop出两个数进行运算
    23. num1 = numStack.pop()
    24. num2 = numStack.pop()
    25. oper = operStack.pop()
    26. res = numStack.cal(num1, num2, oper)
    27. //把运算结果入数栈
    28. numStack.push(res)
    29. //当前符号入符号栈
    30. operStack.push(ch)
    31. } else {
    32. operStack.push(ch)
    33. }
    34. }
    35. } else {
    36. //如果是数,则直接入数栈
    37. //numStack.push(ch - 48)
    38. //1.当处理多位数时,不能发现一个数就立即入栈。因为也可能是多位数
    39. //2.在处理数时,需要像exp表达式后再看一位。如果是数就继续扫描。如果是符号再入栈
    40. //3.定义一个字符串变量,用于拼接
    41. //处理多位数
    42. keepNum += ch
    43. //如果ch已经是exp的最后一位,就直接入栈
    44. if (index == expression.length - 1) {
    45. numStack.push(keepNum.toInt)
    46. } else {
    47. //判断下一个字符是不是数字。如果是数字,就继续扫描。如果是运算符,则入栈
    48. if (operStack.isOper(expression.charAt(index + 1))) {
    49. //如果后一位时运算符,则入栈
    50. numStack.push(keepNum.toInt)
    51. //keepnum清空
    52. keepNum = ""
    53. }
    54. }
    55. }
    56. index = index + 1
    57. }
    58. while (!operStack.isEmpty) {
    59. //如果符号栈为空,则计算到最后的结果,数栈中只有一个数字
    60. num1 = numStack.pop()
    61. num2 = numStack.pop()
    62. oper = operStack.pop()
    63. res = operStack.cal(num1, num2, oper)
    64. numStack.push(res) //入栈
    65. }
    66. println(s"表达式 $expression = ${numStack.pop()}")
    67. }
    68. }
    69. //先创建一个栈
    70. class ArrayStack2 {
    71. private var maxSize: Int = _
    72. private var stack: Array[Int] = _
    73. private var top = -1
    74. //构造器
    75. def this(maxSize: Int) {
    76. this
    77. this.maxSize = maxSize
    78. stack = new Array[Int](this.maxSize)
    79. }
    80. //栈满
    81. def isFull: Boolean = {
    82. top == maxSize - 1
    83. }
    84. //栈空
    85. def isEmpty: Boolean = {
    86. top == -1
    87. }
    88. //返回当前栈顶的值
    89. def peek(): Int = {
    90. stack(top)
    91. }
    92. //入栈-push
    93. def push(value: Int): Unit = {
    94. if (isFull) {
    95. println(s"栈满")
    96. return
    97. }
    98. top = top + 1
    99. stack(top) = value
    100. }
    101. //出栈-pop
    102. def pop(): Int = {
    103. if (isEmpty) {
    104. throw new RuntimeException(s"栈空,没有数据")
    105. }
    106. val value = stack(top)
    107. top = top - 1
    108. value
    109. }
    110. //显示栈的情况【遍历栈】
    111. def list: Unit = {
    112. if (isEmpty) {
    113. println(s"栈空,没有数据")
    114. return
    115. }
    116. //需要从栈顶开始显示
    117. for (i <- 0 to top) {
    118. println(s"stack=${stack(top - i)}")
    119. }
    120. }
    121. //返回运算符的优先级,优先级为自定义
    122. //优先级使用数字表示。数字越大,优先级越高
    123. def priority(oper: Int): Int = {
    124. val ret = oper match {
    125. case '*' | '/' => 1
    126. case '+' | '-' => 0
    127. case _ => -1
    128. }
    129. ret
    130. }
    131. //判断是不是一个运算符
    132. def isOper(value: Char): Boolean = {
    133. value.equals('+') ||
    134. value.equals('-') ||
    135. value.equals('*') ||
    136. value.equals('/')
    137. }
    138. //计算方法
    139. def cal(num1: Int, num2: Int, oper: Int): Int = {
    140. var res: Int = 0 //用于存放计算的结果
    141. res = oper match {
    142. case '+' => num1 + num2
    143. case '-' => num2 - num1
    144. case '*' => num1 * num2
    145. case '/' => num2 / num1
    146. }
    147. res
    148. }
    149. }

    总结:

    Scala在模式匹配+偏函数的结合应用其灵活度太高了,,用顺手了习惯了之后会比Java简化很多。变量声明时也不用像Java一样一个变量new一次对象,可以像下面这样:

     

  • 相关阅读:
    Redis入门完整教程:Redis Shell
    生活中常见的嵌入式产品都有哪些?
    资源受限MCU Flash空间占用优化
    代码随想录算法训练营 day46|139.单词拆分
    [思考进阶]01 如何克服自己的无知?
    镭速如何解决UDP传输不通的问题
    FreeSWITCH 1.10.10 简单图形化界面9 - 鼎兴FXO网关SIP中继内网IPPBX落地
    Mybatis的动态sql
    返回多维数组转换为一维后的数组:array.flatten()
    Vue.prototype详解
  • 原文地址:https://blog.csdn.net/d905133872/article/details/132718353