栈是一种受限的线性表,它规定只能够在表的尾部进行插入和删除,我们把允许插入和删除元素的一端称为栈顶,而另一段称为栈底,没有任何元素的元素栈称为空栈。
栈中的元素进出的规则为先入后出,即先进入栈的元素后出栈而后进入栈的元素先出栈。在对栈栈中的元素进行操作时只能够操作栈顶的元素。
当储存的元素超过了栈的储存空间则会发生栈中元素的溢出。
两个栈之间的空间共享:栈的线性储存在一开始就会指定使用多少内存空间来储存数据,但当我们向栈中储存的数据量大于栈内存时则超出部分无法储存,若此时还有另外一个栈,在这个栈中储存空间还没有用完,则很浪费,我们可以将两个栈链接实现栈之间的空间共享,链接方式为将一个栈的栈底与另一个栈的栈顶链接,此时这个栈的栈顶下标改为上一个栈的储存空间大小n-1
栈的顺序储存优点 :
只需要记录栈顶的元素的位置而不用记录元素的插入位置,而且在插入元素的时候不用再移动元素。
栈的顺序存储缺点 :
栈的顺序储存在一开始会分配固定大小内存空间来储存元素,在后面存储元素的时候内存空间不容易扩展。
在计算机体系中栈为一个动态内存区域,程序在执行的过程中栈可以保存函数函数在调用时所需要的所有信息,这些信息包括:
1、函数的返回地址和参数
2、保存函数内部的非静态局部变量和一些编译器生成的零时变量
package main
import (
"errors"
"fmt"
)
type SElemmType int
const MaxSize = 20
//定义一个栈
type SqStack struct {
data [MaxSize]SElemmType
top int//指向存储数据的位置(没有数据为:-1)
}
//入栈
func Push(s *SqStack, e SElemmType) (err error) {
if s.top == MaxSize-1 {
err = errors.New("栈已满,不能入栈")
}
s.top++ //top指针指向上一次元素所在位置,初始化为-1
s.data[s.top] = e
return
}
//出栈
func Pop(s *SqStack) (err error, res SElemmType) {
if s.top == -1 {
err = errors.New("栈已空,不能出栈")
return
}
res = s.data[s.top]
s.top--//top指向栈顶元素
return
}
func main() {
var sqs SqStack
sqs.top = -1 //初始化很重要,top从-1开始
Push(&sqs, SElemmType(1))
Push(&sqs, SElemmType(2))
Push(&sqs, SElemmType(3))
Push(&sqs, SElemmType(4))
Push(&sqs, SElemmType(5))
_, res := Pop(&sqs)
fmt.Println("第1次出栈", res)
_, res = Pop(&sqs)
fmt.Println("第2次出栈", res)
_, res = Pop(&sqs)
fmt.Println("第3次出栈", res)
_, res = Pop(&sqs)
fmt.Println("第4次出栈", res)
_, res = Pop(&sqs)
fmt.Println("第5次出栈", res)
err, res := Pop(&sqs)
fmt.Println("第6次出栈", err, res)
}