栈(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) { // fmt.Println(len(s.Array)) // 判断栈是否满了 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) { // fmt.Println(len(s.Array)) // 判断栈是否满了 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 { // 这些数字是加减乘除对于的ASSIC码 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, 帮助扫描exp index := 0 // 辅助变量 num1 := 0 num2 := 0 oper := 0 result := 0 keepNum := "" for { // 循环遍历每一个字符 ch := exp[index : index+1] // 字符转化为ASSIC码 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 { // 说明是数字 // 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(num1, num2, oper) //将计算结果重新入数栈 numStack.Push(result) } // 此时栈中的最后一个数就是结果 res := numStack.Pop() fmt.Printf("表达式%s = %v", exp, res) }
完整代码:https://github.com/bigzoro/go_algorithm/tree/main/stack