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

代码:

Scala 复制代码
package Algotithm.stack

object Calculator {
  def main(args: Array[String]): Unit = {
    val expression = "3+2*6-2"
    //创建两个栈:数栈、符号栈
    val numStack, operStack = new ArrayStack2(10)
    //定义需要的相关变量
    var index, num1, num2, oper, res = 0 //用于扫描
    var ch: Char = ' ' //每次扫描得到的char保存到ch
    var keepNum: String = ""
    //开始循环扫描入栈
    while (index < expression.length) {
      ch = expression.charAt(index)
      //判断是什么
      if (operStack.isOper(ch)) {
        if (operStack.isEmpty) {
          //如果为空直接入栈
          operStack.push(ch)
        } else {
          //如果不为空
          if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
            //从数栈中pop出两个数进行运算
            num1 = numStack.pop()
            num2 = numStack.pop()
            oper = operStack.pop()
            res = numStack.cal(num1, num2, oper)
            //把运算结果入数栈
            numStack.push(res)
            //当前符号入符号栈
            operStack.push(ch)
          } else {
            operStack.push(ch)
          }
        }
      } else {
        //如果是数,则直接入数栈
        //numStack.push(ch - 48)
        //1.当处理多位数时,不能发现一个数就立即入栈。因为也可能是多位数
        //2.在处理数时,需要像exp表达式后再看一位。如果是数就继续扫描。如果是符号再入栈
        //3.定义一个字符串变量,用于拼接

        //处理多位数
        keepNum += ch
        //如果ch已经是exp的最后一位,就直接入栈
        if (index == expression.length - 1) {
          numStack.push(keepNum.toInt)
        } else {
          //判断下一个字符是不是数字。如果是数字,就继续扫描。如果是运算符,则入栈
          if (operStack.isOper(expression.charAt(index + 1))) {
            //如果后一位时运算符,则入栈
            numStack.push(keepNum.toInt)
            //keepnum清空
            keepNum = ""
          }
        }

      }
      index = index + 1
    }

    while (!operStack.isEmpty) {
      //如果符号栈为空,则计算到最后的结果,数栈中只有一个数字
      num1 = numStack.pop()
      num2 = numStack.pop()
      oper = operStack.pop()
      res = operStack.cal(num1, num2, oper)
      numStack.push(res) //入栈
    }
    println(s"表达式 $expression = ${numStack.pop()}")
  }
}

//先创建一个栈
class ArrayStack2 {
  private var maxSize: Int = _
  private var stack: Array[Int] = _
  private var top = -1

  //构造器
  def this(maxSize: Int) {
    this
    this.maxSize = maxSize
    stack = new Array[Int](this.maxSize)
  }

  //栈满
  def isFull: Boolean = {
    top == maxSize - 1
  }

  //栈空
  def isEmpty: Boolean = {
    top == -1
  }

  //返回当前栈顶的值
  def peek(): Int = {
    stack(top)
  }

  //入栈-push
  def push(value: Int): Unit = {
    if (isFull) {
      println(s"栈满")
      return
    }
    top = top + 1
    stack(top) = value
  }

  //出栈-pop
  def pop(): Int = {
    if (isEmpty) {
      throw new RuntimeException(s"栈空,没有数据")
    }
    val value = stack(top)
    top = top - 1
    value
  }

  //显示栈的情况【遍历栈】
  def list: Unit = {
    if (isEmpty) {
      println(s"栈空,没有数据")
      return
    }
    //需要从栈顶开始显示
    for (i <- 0 to top) {
      println(s"stack=${stack(top - i)}")
    }
  }

  //返回运算符的优先级,优先级为自定义
  //优先级使用数字表示。数字越大,优先级越高
  def priority(oper: Int): Int = {
    val ret = oper match {
      case '*' | '/' => 1
      case '+' | '-' => 0
      case _ => -1
    }
    ret
  }

  //判断是不是一个运算符
  def isOper(value: Char): Boolean = {
    value.equals('+') ||
      value.equals('-') ||
      value.equals('*') ||
      value.equals('/')
  }

  //计算方法
  def cal(num1: Int, num2: Int, oper: Int): Int = {
    var res: Int = 0 //用于存放计算的结果
    res = oper match {
      case '+' => num1 + num2
      case '-' => num2 - num1
      case '*' => num1 * num2
      case '/' => num2 / num1
    }
    res
  }

}

总结:

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

相关推荐
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假6 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠7 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦13 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠14 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾15 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82115 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q15 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒15 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记15 天前
单项不带头不循环链表
数据结构·链表