scala使用数组模拟栈,使用栈模拟计算器运算

package datastructure.stack

import java.util.Scanner
import scala.reflect.ClassTag
import scala.util.control.Breaks

/**
 * 使用数组模拟栈
 */
class ArrayStack[T: ClassTag]() {
  private var maxSize: Int = _
  private var top: Int = -1 //栈顶
  private var stack: Array[T] = _ //数组模拟栈存放数据
  def this(maxSize: Int) = {
    this()
    this.maxSize = maxSize
    this.stack = new Array[T](maxSize)
  }

  def getMaxSize: Int = this.maxSize //栈最大空间


  def ifFull: Boolean = top == maxSize-1
  def isEmpty: Boolean = top == -1
  //入栈
  def push(value: T):Unit = {
    if (ifFull) {
      println("栈满")
      return
    }
    top +=  1
    stack(top) = value
  }
  //出栈
  def pop(): T = {
    if(isEmpty){
      throw new RuntimeException("stack is empty")
    }
    val value = stack(top)
    top -= 1
    value
  }

  //查看栈顶值 但不是真的弹出栈
  def peek(): T = stack(top)
  //遍历栈:注意要从栈顶开始取元素
  def show(): Unit = {
    if(isEmpty){
      println("栈空,没有数据")
      return
    }
    for( i <- top to 0 by -1){
      println(s"stack($i)=${stack(i)}")
    }
  }
}
object ArrayStack{
  def apply[T: ClassTag](maxSize: Int): ArrayStack[T] = new ArrayStack(maxSize)
}
object Demo{
  def main(args: Array[String]): Unit = {
    val stack = ArrayStack[Int](4)
    var key = ""
    var loop = true
    val sc = new Scanner(System.in)
    while (loop){
      println("show:显示栈")
      println("pop:取出栈顶元素")
      println("push:添加数据到栈")
      key = sc.next()
      key match {
        case "show" =>
          stack.show()
        case "push" =>
          println("输入一个整数")
          val value = sc.nextInt()
          stack.push(value)
        case "pop" =>
          try {
            val i = stack.pop()
            println(s"出栈数据为:$i")
          } catch {
            case e: Exception => println(e.getMessage)
          }
        case _ =>
          sc.close()
          loop = false
          println("程序退出")
      }
    }
  }
}

/**
 * 基于栈模拟计算器
 */
object Calculator{
  /**
   * 假定只有加减乘除
   * @param oper
   * @return
   */
  def getPrio(oper: Char): Int ={
    if(oper == '*' || oper == '/'){
      1
    } else if(oper == '+' || oper == '-'){
      0
    }else{
      -1
    }
  }

  /**
   * 是否为运算符
   * @param oper
   * @return
   */
  def isOper(oper: Char) = {
    oper == '*' || oper == '/' || oper == '+' || oper == '-'
  }

  def cal(num1:Int, num2: Int, oper: Char): Int = {
    oper match {
      case '+' => num1+num2
      case '-' => num2-num1
      case '*' => num1*num2
      case '/' => num2/num1
    }
  }

  def main(args: Array[String]): Unit = {
    val exp = "30+2*60-2"
    val numStack = ArrayStack[Int](10)
    val operStack = ArrayStack[Char](10)
    var index = 0
    var num1 = 0
    var num2 = 0
    var oper:Char = ' '
    var res = 0
    var ch:Char = ' '
    val ctrl = new Breaks
    var keepNum = ""
    ctrl.breakable(
      while (true) {
        //依次得到每一个字符
        ch = exp.substring(index,index+1).charAt(0)
        if(isOper(ch)){//如果是运算符
          if(!operStack.isEmpty){
            //如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符, 就需要从数栈中 pop 出两个数,
            // 在从符号栈中 pop 出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
            if (getPrio(ch) <= getPrio(operStack.peek())){
              num1 = numStack.pop()
              num2 = numStack.pop()
              oper = operStack.pop()
              res = cal(num1, num2, oper)
              numStack.push(res)
              operStack.push(ch)
            }else{//否则直接入栈
              operStack.push(ch)
            }
          }else{//如果为空入符号栈
            operStack.push(ch)
          }
        }else{
          //可能是多位数,如果后一位是符号就停止扫描
          keepNum += ch
          //如果ch已经是exp最后一位了不需要判断,直接入栈
          if(index==exp.length-1){
            numStack.push(keepNum.toInt)
          }else{//否则如果后一位是符号才入栈
            if(isOper(exp.substring(index+1,index+2).charAt(0))){
              numStack.push(keepNum.toInt)
              keepNum=""
            }
          }
        }
        index += 1
        if (index>=exp.length){
          ctrl.break()
        }
      }
    )
    //表达式扫描完毕执行运算
    ctrl.breakable(
      while (true){
        //如果符号栈为空则计算到最后的结果,跳出循环
        if( operStack.isEmpty){
          ctrl.break()
        }
        num1 = numStack.pop()
        num2 = numStack.pop()
        oper = operStack.pop()
        res = cal(num1, num2, oper)
        numStack.push(res)
      }
    )
    println(s"表达式:$exp")
    println(s"结果:${numStack.pop()}")
  }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值