《大话数据结构》学习笔记 —— 04 栈(golang实现)



定义

栈是一个后进先出的(Last in first out, LIFO)的线性表,它限定仅在表尾进行删除和插入操作



关键词


栈顶、栈底

允许插入和删除的一端称为栈顶,另一端称为栈底。


空栈

不包含任何数据元素的栈称为空栈。


栈的插入操作

栈的插入操作,叫作进栈,也称压栈入栈


栈的删除操作

栈的删除操作,叫作出栈,也称弹栈



栈的顺序存储结构


进栈操作示意图:

在这里插入图片描述


代码实现

package StackArray

// 栈的接口
type StackArray interface {

	// 进栈
	Push(data interface{}) bool

	// 出栈
	Pop() interface{}

	// 判断是否满
	IsFull() bool

	// 判断是否空
	IsEmpty() bool

	// 获取栈大小
	Size() int

	// 清空栈
	Clear()
}

// 栈的结构
type Stack struct {

	// 数据域
	dataSource []interface{}

	// 最大空间
	capsize int

	// 当前大小
	currentsize int
}

// 初始化栈
func NewStack() *Stack {

	// 初始化结构体
	mystack := new(Stack)

	// 开辟内存空间
	mystack.dataSource = make([]interface{}, 0, 10)

	// 初始化最大空间
	mystack.capsize = 10

	// 初始化当前大小
	mystack.currentsize = 0

	return mystack
}

// 进栈
func (stack *Stack) Push(data interface{}) bool {

	// 已满
	if stack.IsFull() {
		return false
	}

	// 数据加入到数据域
	stack.dataSource = append(stack.dataSource, data)

	// 大小加1
	stack.currentsize++

	return true
}

// 出栈
func (stack *Stack) Pop() interface{} {

	// 为空
	if stack.IsEmpty() {
		return nil
	}

	// 最后一个元素
	last := stack.dataSource[stack.currentsize-1]

	// 重设数据域
	stack.dataSource = stack.dataSource[:stack.currentsize-1]

	// 大小减去1
	stack.currentsize--

	return last
}

// 判断是否满
func (stack *Stack) IsFull() bool {
	return stack.currentsize >= stack.capsize
}

// 判断是否空
func (stack *Stack) IsEmpty() bool {
	return stack.currentsize == 0
}

// 获取栈大小
func (stack *Stack) Size() int {
	return stack.currentsize
}

// 清空栈
func (stack *Stack) Clear() {

	// 重新开辟内存空间
	stack.dataSource = make([]interface{}, 0, 10)

	// 重新初始化最大空间
	stack.capsize = 10

	// 重新初始化当前大小
	stack.currentsize = 0
}



栈的链式存储结构

链栈绝大部分的操作和单链表类似,所以不再赘述,直接上代码。



代码实现

package StackLink

import "errors"

// 链式栈接口
type StackLink interface {

	// 进栈
	Push(data interface{})

	// 出栈
	Pop() (interface{}, error)

	// 获取栈长度
	Length() int

	// 判断是否空
	IsEmpty() bool
}

// 链式栈结点
type Node struct {
	value interface{}
	pNext *Node
}

// 初始化链式栈
func NewStackLink() *Node {
	return &Node{}
}

// 进栈(头部插入)
func (n *Node) Push(data interface{}) {

	// 新结点
	newNode := &Node{
		value: data,
		// 头结点的指针赋值给新结点的指针
		pNext: n.pNext,
	}

	// 头结点指向新结点
	n.pNext = newNode
}

// 出栈
func (n *Node) Pop() (interface{}, error) {

	// 链栈为空
	if n.IsEmpty() == true {
		return nil, errors.New("空链栈")
	}

	// 获取第一个元素的值
	value := n.pNext.value

	// 头结点指向原来的第二个元素
	n.pNext = n.pNext.pNext

	return value, nil
}

// 获取栈长度
func (n *Node) Length() int {

	// 备份头结点
	pnext := n

	// 初始化长度
	length := 0

	// 循环到末尾
	for pnext.pNext != nil {
		pnext = pnext.pNext
		length++
	}

	return length
}

// 判断是否空
func (n *Node) IsEmpty() bool {
	return n.pNext == nil
}



练习


1. 栈实现递归

实现1+2+3…+5

// 初始化栈
mystack := StackArray.NewStack()

// 保存结果
last := 0

// 压入
mystack.Push(5)

for !mystack.IsEmpty() {

	// 取出数据
	data := mystack.Pop()
	if data == 0 {
		last += 0
	} else {
		last += data.(int)
		mystack.Push((data.(int) - 1))
	}
}

2. 栈实现斐波拉切数列
// 初始化栈
mystack := StackArray.NewStack()

// 保存结果
last := 0

// 压入
mystack.Push(7)

for !mystack.IsEmpty() {

	// 取出数据
	data := mystack.Pop()
	if data == 1 || data == 2 {
		last += 1
	} else {
		last += data.(int)
		mystack.Push((data.(int) - 1))
		mystack.Push((data.(int) - 2))
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值