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()}")
}
}
scala使用数组模拟栈,使用栈模拟计算器运算
最新推荐文章于 2024-07-12 21:20:02 发布