栈的英文为(stack)
栈是一个先入后出(FILO-First ln Last Out)的有序列表。
栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。
根据堆栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。
出栈和入栈的概念
实例
package main
import (
"fmt"
"errors"
)
//使用数组来模拟一个栈的使用
type Stack struct {
MaxTop int //表示我们栈最大可以存放的个数
Top int //表示栈顶,因为栈顶固定 ,因此我们直接使用Top
arr [5]int //数组模拟战
}
//入栈
func (this *Stack) Push(val int) (err error){
//先判断栈是否满了
if this.Top == this.MaxTop -1 {
fmt.Println("stack full")
return errors.New("stack full")
}
this.Top ++
//放入数据
this.arr[this.Top]=val
return
}
//遍历栈,需要从栈顶开始遍历
func (this *Stack) List(){
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return
}
fmt.Println("栈的情况如下:")
for i := this.Top;i>=0;i--{
fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
}
}
//出栈
func (this *Stack) Pop()(val int,err error){
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return 0,errors.New("stack empty")
}
//先取值,再this.Top--
val = this.arr[this.Top]
this.Top--
return val,nil
}
func main(){
stack := &Stack{
MaxTop : 5, //表示最多存放五个数到栈中
Top : -1, //当前栈顶为-1,表示栈为空
}
//入栈
stack.Push(2)
// stack.Push(3)
stack.Push(22)
stack.Push(45)
stack.Push(58)
stack.Push(88)
//显示
stack.List()
val,_:=stack.Pop()
fmt.Println("出栈val=",val)
//显示
stack.List()
}
栈的计算表达式
分析
代码实现
package main
import (
"fmt"
"errors"
"strconv"
)
//使用数组来模拟一个栈的使用
type Stack struct {
MaxTop int //表示我们栈最大可以存放的个数
Top int //表示栈顶,因为栈顶固定 ,因此我们直接使用Top
arr [20]int //数组模拟战
}
//入栈
func (this *Stack) Push(val int) (err error){
//先判断栈是否满了
if this.Top == this.MaxTop -1 {
fmt.Println("stack full")
return errors.New("stack full")
}
this.Top ++
//放入数据
this.arr[this.Top]=val
return
}
//遍历栈,需要从栈顶开始遍历
func (this *Stack) List(){
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return
}
fmt.Println("栈的情况如下:")
for i := this.Top;i>=0;i--{
fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
}
}
//出栈
func (this *Stack) Pop()(val int,err error){
//先判断栈是否为空
if this.Top == -1 {
fmt.Println("stack empty")
return 0,errors.New("stack empty")
}
//先取值,再this.Top--
val = this.arr[this.Top]
this.Top--
return val,nil
}
//判断一个字符是不是一个运算符[+, - , * ,/]
func (this *Stack) IsOper(val int ) bool{
//根据ASCII来判断
if val == 42 || val == 43 ||val==45||val==47{
return true
}else{
return false
}
}
//运算的方法
func (this *Stack) Cal(num1 int ,num2 int,oper int) int {
res := 0
switch oper{
case 42 :
res = num1 * num2
case 43 :
res = num1 + num2
case 45 :
res = num1 - num2
case 47 :
res = num1 / num2
default :
fmt.Println("运算符错误.")
}
return res
}
//编写一个方法 ,返回某个运算符的优先级【自己定义】
func (this *Stack) Priority(oper int) int {
res :=0
if oper == 42 || oper == 47{
res = 1
}else if oper ==43 || oper ==45 {
res = 0
}
return res
}
func main(){
//数栈
numStack := &Stack{
MaxTop : 20,
Top : -1,
}
//符号栈
operStack := &Stack{
MaxTop : 20,
Top : -1,
}
exp := "30+3*6-2"
//定义一个index ,帮助扫描exp
index :=0
//为了配合运算,我们定义需要的变量
num1 := 0
num2 := 0
oper := 0
result := 0
keepNum := ""
for {
ch := exp[index:index + 1] //字符串
temp := int([]byte(ch)[0]) //就是字符对应的ASCII码
if operStack.IsOper(temp) { //说明的符号
//如果operStack 是一个空栈 ,直接入栈
if operStack.Top ==-1{ //空栈
operStack.Push(temp)
}else{
//如果发现opertstack栈项的运算符的优先级大于等于当前准备入栈的运算符的优先级
//,就从符号栈pop出, 并从数栈也pop两个数,进行运算,运算后的结果再重新入栈到
//数栈,符号再入符号栈
if operStack.Priority(operStack.arr[operStack.Top]) >=
operStack.Priority(temp){
num1,_=numStack.Pop()
num2,_=numStack.Pop()
oper,_=operStack.Pop()
result = operStack.Cal(num1,num2,oper)
//将计算的结构重新入数栈
numStack.Push(result)
//当前的符号压入符号栈
operStack.Push(temp)
}else {
operStack.Push(temp)
}
}
}else{ //说明是数
//处理多位数的思路
//1.定义-一个变量keepNum string, 做拼接
keepNum += ch
//2.每次要向index的前面字符测试一下,看看是不是运算符,然后处理
//如果已经到表达式最后,直接keepNum
if index == len(exp) -1 {
val,_ := strconv.ParseInt(keepNum,10,64)
numStack.Push(int(val))
}else{
//向index,后面测试看看是不是运算符【index】
if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])){
val,_ := strconv.ParseInt(keepNum,10,64)
numStack.Push(int(val))
keepNum = ""
}
}
}
//继续扫描
//先判断index是否已经扫描到计算表达式的最后
if index +1 == len(exp){
break
}
index++
}
//如果扫描表达式完毕,依次从符号栈取出符号,然后从数栈取出两个数,
//运算后的结果,入数栈,直到符号栈为空
for {
if operStack.Top == -1 {
break //退出条件
}
num1,_=numStack.Pop()
num2,_=numStack.Pop()
oper,_=operStack.Pop()
result = operStack.Cal(num2,num1,oper)
//将计算的结构重新入数栈
numStack.Push(result)
}
//如果我们的算法没有问题,表达式也是正确的,则结果就是numStack最后数
res,_ := numStack.Pop()
fmt.Printf("表达式%s=%v",exp,res)
}