概述
栈(stack)是一种先进后出(First In Last Out, FILO)的特殊线性表,其插入和删除操作只允许在线性表的一段进行。允许操作的一端称为栈顶(top),不允许操作的一端称为栈底(bottom)。栈中插入元素的操作称为入栈(push),删除元素的操作称为出栈(pop)。
常用的应用场景:
- 子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中
- 处理递归调用:和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数、区域变量等数据存入到堆栈中
- 表达式的转换与求值
- 二叉树的遍历
- 图形的深度优先搜索算法
顺序栈
type Stack struct {
MaxTop int
Top int
Array [5]int
}
func (s *Stack) Push(val int) {
if s.Top >= s.MaxTop-1 {
fmt.Println("the stack is full")
return
}
s.Top++
s.Array[s.Top] = val
return
}
func (s *Stack) Pop() (data int) {
if s.Top == -1 {
fmt.Println("the stack is empty")
return
}
data = s.Array[s.Top]
s.Top--
return
}
func (s *Stack) List() {
if s.Top == -1 {
fmt.Println("the stack is empty")
return
}
for i := s.Top; i >= 0; i-- {
fmt.Println(s.Array[i])
}
}
链式栈
type Node struct {
data int
next *Node
}
type Stack struct {
maxLength int
length int
head *Node
}
func InitStack(maxLength int) *Stack {
return &Stack{
maxLength: maxLength,
length: 0,
head: nil,
}
}
func (s *Stack) Push(val int) {
if s.length >= s.maxLength {
fmt.Println("the stack is full")
return
}
node := &Node{
data: val,
next: s.head,
}
s.head = node
s.length++
}
func (s *Stack) Pop() (data int, err error) {
if s.length <= 0 {
err = errors.New("the stack is empty")
return
}
data = s.head.data
s.head = s.head.next
s.length--
return
}
func (s *Stack) List() {
if s.length == 0 {
fmt.Println("the stack is empty")
return
}
temp := s.head
for i := 0; i < s.length; i++ {
fmt.Println(temp.data)
temp = temp.next
}
}
求算术表达式
type Stack struct {
MaxTop int
Top int
Array [20]int
}
func (s *Stack) Push(val int) {
if s.Top >= s.MaxTop-1 {
fmt.Println("the stack is full")
return
}
s.Top++
s.Array[s.Top] = val
return
}
func (s *Stack) Pop() (data int) {
if s.Top == -1 {
fmt.Println("the stack is empty")
return
}
data = s.Array[s.Top]
s.Top--
return
}
func (s *Stack) List() {
if s.Top == -1 {
fmt.Println("the stack is empty")
return
}
for i := s.Top; i >= 0; i-- {
fmt.Println(s.Array[i])
}
}
func (s *Stack) IsOper(val int) bool {
if val == 42 || val == 43 || val == 45 || val == 47 {
return true
} else {
return false
}
}
func (s *Stack) Cal(num1 int, num2 int, oper int) int {
res := 0
switch oper {
case 42:
res = num2 * num1
case 43:
res = num2 + num1
case 45:
res = num2 - num1
case 47:
res = num2 / num1
default:
fmt.Println("运算符错误")
}
return res
}
func (s *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 := "3+2*6-2"
index := 0
num1 := 0
num2 := 0
oper := 0
result := 0
keepNum := ""
for {
ch := exp[index : index+1]
temp := int([]byte(ch)[0])
if operStack.IsOper(temp) {
if operStack.Top == -1 {
operStack.Push(temp)
} else {
if operStack.Priority(operStack.Array[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 {
keepNum += ch
if index == len(exp)-1 {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
} else {
if operStack.IsOper(int([]byte(exp[index+1 : index+2])[0])) {
val, _ := strconv.ParseInt(keepNum, 10, 64)
numStack.Push(int(val))
keepNum = ""
}
}
}
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(num1, num2, oper)
numStack.Push(result)
}
res := numStack.Pop()
fmt.Printf("表达式%s = %v", exp, res)
}
最后
完整代码:https://github.com/bigzoro/go_algorithm/tree/main/stack
|