栈的介绍:
- 栈是一个先入后出的有序列表
- 栈(stack)是线制性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(top),另一端为固定的一端,称为栈底(Bottom)。
- 栈和堆栈是同一个概念
- 最先放入栈中的元素在栈底,最后放入的元素在栈顶
- 删除元素:最后放入栈中的元素先删除,最先放入的最后删除
- 栈的使用场景:子程序的调用(在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中),递归,表达式的转换与求值等
示意图:
栈的实现有两种方法,分别为采用数组来实现和采用链表来实现,这里我们采用数组来实现。
解题思路:
- 可以把数组的首元素当作栈底,同时记录栈中元素的个数size
- 如图,压栈的操作是把待压栈的元素放到数组arr[size]中,然后执行size++操作。
- 同2原理,弹栈操作是取数组arr[size-1]元素,然后执行size–操作。
- 根据以上分析可以很容易实现栈
代码如下:
package main
import (
"errors"
"fmt"
)
//使用结构体管理栈
type sliceStack struct {
arr []interface{} //切片
stackSize int //栈中元素的个数
}
//创建栈
func newSliceStack() *sliceStack {
return &sliceStack{arr: make([]interface{}, 0)}
}
//判断是否为空
func (p *sliceStack) isEmpty() bool {
return p.stackSize == 0
}
//栈的大小
func (p *sliceStack) size() int {
return p.stackSize
}
//返回栈顶元素
func (p *sliceStack) top() interface{} {
if p.isEmpty() { //说明栈为空
return nil
}
return p.arr[p.stackSize-1] //栈顶元素
}
//push栈元素
func (p *sliceStack) push(t interface{}) {
p.arr = append(p.arr, t)
p.stackSize = p.stackSize + 1
}
//pop栈元素
func (p *sliceStack) pop() interface{} {
if p.stackSize > 0 { //栈不为空时
p.stackSize--
element := p.arr[p.stackSize]
p.arr = p.arr[:p.stackSize]
return element
}
return errors.New("栈为空")
}
//显示栈的元素
func (p *sliceStack) print() {
fmt.Println("栈当前的情况是")
if p.isEmpty() {
fmt.Println("当前栈为空")
}
for i := p.stackSize - 1; i > 0; i-- {
fmt.Println(i, "->", p.arr[i])
}
}
func main() {
var stack = newSliceStack()
if stack.isEmpty() {
fmt.Println("Stack为空! ")
} else {
fmt.Println("Stack不为空! ", stack.stackSize)
}
fmt.Println("\nstack增加字符串元素: ")
stack.push("中文元素")
stack.push("elem1")
stack.push(10)
stack.push(20)
stack.push(30)
stack.print()
fmt.Println("当前Size = ", stack.size())
fmt.Println("当前Top = ", stack.top())
fmt.Println("取出元素", stack.pop())
stack.print()
//结果:
//Stack为空!
//
//stack增加字符串元素:
//栈当前的情况是
//4 -> 30
//3 -> 20
//2 -> 10
//1 -> elem1
//当前Size = 5
//当前Top = 30
//取出元素 30
//栈当前的情况是
//3 -> 20
//2 -> 10
//1 -> elem1
}