一、栈定义
栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,这时我们就应该首选“栈”这种数据结构。 栈主要包含两个操作,入栈和出栈,也就是在栈顶插入一个数据和从栈顶删除一个数据。
栈既可以用数组来实现,也可以用链表来实现。用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。
二、复杂度分析
不管是顺序栈还是链式栈,我们存储数据只需要一个大小为 n 的数组就够了。在入栈和出栈过程中,只需要一两个临时变量存储空间,所以空间复杂度是 O(1)。
不管是顺序栈还是链式栈,入栈、出栈只涉及栈顶个别数据的操作,所以时间复杂度都是 O(1)。
三、栈的实现
//顺序栈的实现
package main
import "fmt"
type Stack struct {
element []int
}
//创建一个新栈
func NewStack()*Stack{
return &Stack{}
}
//判断栈是否为空
func (s *Stack)IsEmpty()bool{
if len(s.element) == 0 {
return true
}else {
return false
}
}
//求栈的长度
func (s *Stack)GetStackLength()int{
return len(s.element)
}
//进栈操作
func (s *Stack)Push(value int) {
s.element = append(s.element, value)
}
//获取栈顶元素
func (s *Stack)Top()(int, bool) {
if s.IsEmpty() {
return -1, false
}else{
return s.element[s.GetStackLength()-1], true
}
}
//出栈操作
func (s *Stack)Pop()bool{
if s.IsEmpty(){
return false
}else{
s.element = s.element[:s.GetStackLength()-1]
}
return true
}
//打印堆栈
func (s *Stack)Print(){
for i := s.GetStackLength()-1;i >= 0;i--{
fmt.Printf("%d ", s.element[i])
}
fmt.Printf("\n")
}
func main(){
stack := NewStack()
stack.Push(1)
stack.Push(3)
stack.Push(5)
stack.Push(7)
fmt.Printf("stack size = %d\n", stack.GetStackLength())
stack.Print()
stack.Pop()
stack.Print()
top,_ := stack.Top()
fmt.Printf("%d\n", top)
}
//链栈
package main
import "fmt"
//节点
type Node struct {
next *Node
data int
}
//链式栈
type LinkStack struct {
head *Node
length int
}
//创建节点
func CreateNode(value int) *Node{
return &Node{
nil,
value,
}
}
//创建链表,初始化一个空头节点
func CreateLinkStack() *LinkStack{
return &LinkStack{
&Node{
nil,
0,
},
0,
}
}
//判断栈是否为空
func (stack *LinkStack)StackEmpty()bool{
return stack.head.next == nil
}
//进栈操作
func (stack *LinkStack)Push(data int){
p := CreateNode(data)
p.next = stack.head.next
stack.head.next = p
stack.length++
}
//出栈操作
func (stack *LinkStack)Pop()int{
if stack.head.next == nil{
return -999
}
p := stack.head.next
data := p.data
stack.head.next = p.next
p = nil
stack.length--
return data
}
//获取栈顶元素
func (stack *LinkStack)Top()int{
if stack.head.next == nil{
return -999
}
data := stack.head.next.data
return data
}
func main(){
stack := CreateLinkStack()
stack.Push(3)
stack.Push(4)
stack.Push(5)
stack.Push(6)
fmt.Printf("%d\n", stack.Top())
stack.Pop()
fmt.Printf("%d\n",stack.Top())
}
四、栈的应用
1、表达式求值
2、括号匹配
声明:本文参考极客时间《数据结构与算法之美》