Go数据结构之简单栈的初体验

一、栈的实现

1. 栈是什么

对于我们新手小白们,只需要记住的是:栈的特点是 先进后出 

可以简答理解为,一个杯子,我们往里面加水,然后再喝水,先加进去的水,在杯底,所以最后才倒出来,这就是栈

因此,在某些应用场景下,我们或许需要自定义一个栈,例如游戏中的枪械,弹匣内子弹的压入和弹出,就类似栈

2. 实现代码

要实现栈,首先要知道栈需要什么方法:

  1. 栈的大小
  2. 清空栈
  3. 往栈内压入元素
  4. 将栈内元素弹出
  5. 判断栈的状态

话不多说,看看代码:

package stackArray

// StackArray 栈
type StackArray[T any] interface {
	Clear()
	IsEmpty() bool
	IsFull() bool
	Size() int
	Pop() T      // 弹出
	Push(data T) // 压入
}

type Stack[T any] struct {
	dataSource  []T
	capSize     int // 最大空间
	currentSize int // 当前已使用
}

func NewStack[T any](capSize int) StackArray[T] {
	return &Stack[T]{
		dataSource:  make([]T, 0, capSize),
		capSize:     capSize,
		currentSize: 0,
	}
}

func (s *Stack[T]) Clear() {
	s.dataSource = make([]T, 0, s.capSize)
	s.currentSize = 0
}

func (s *Stack[T]) IsEmpty() bool {
	if s.currentSize == 0 {
		return true
	}
	return false
}

func (s *Stack[T]) IsFull() bool {
	if s.currentSize == s.capSize {
		return true
	}
	return false
}

func (s *Stack[T]) Size() int {
	return s.currentSize
}

func (s *Stack[T]) Pop() T {
	if !s.IsEmpty() {
		// 拿到最后一个元素
		last := s.dataSource[s.currentSize-1]
		s.dataSource = s.dataSource[:s.currentSize-1]
		s.currentSize--
		return last
	}
	var zero T
	return zero
}

func (s *Stack[T]) Push(data T) {
	if !s.IsFull() {
		s.dataSource = append(s.dataSource, data)
		s.currentSize++
	}
}

依旧保持依赖注入风格和接口的定义,这是为了防止用户随意的使用 Stack 中的成员,可以看到非常的简单。

二、栈+数组的实现

上一期,我们定义了一个简单的数组和它的迭代器

直通车:Go数据结构之简单数组及其迭代器

可以发现,我们的栈的定义里,也使用到了数组,所以我们可以结合上期所创建的数组,将自定义栈里的函数,简化为对数组接口内方法的操作

1. 实现代码

package list

// StackArrayX
type StackArrayX[T any] interface {
	Clear()
	IsEmpty() bool
	IsFull() bool
	Size() int
	Pop() T      // 弹出
	Push(data T) // 压入
}

type StackX[T any] struct {
	myArray List[T]
    // 引入迭代器
	MyIt    Iterator[T]
	capSize int
}

func NewStackX[T any](capSize int) StackArrayX[T] {
	myStack := new(StackX[T])
	if capSize <= 0 {
		myStack.capSize = 10
	}
	myStack.myArray = NewArrayList[T](capSize)
	myStack.MyIt = myStack.myArray.Iterator()
	return myStack
}

func (s *StackX[T]) Clear() {
	s.myArray.Clear()
}

func (s *StackX[T]) IsEmpty() bool {
	if s.myArray.Size() == 0 {
		return true
	}
	return false
}

func (s *StackX[T]) IsFull() bool {
	if s.myArray.Size() == s.capSize {
		return true
	}
	return false
}

func (s *StackX[T]) Size() int {
	return s.myArray.Size()
}

func (s *StackX[T]) Pop() T {
	if !s.IsEmpty() {
		size := s.myArray.Size()
		// 拿到最后一个元素
		last, _ := s.myArray.Get(size - 1)
		s.myArray.Delete(size - 1)
		return last
	}
	var zero T
	return zero
}

func (s *StackX[T]) Push(data T) {
	if !s.IsFull() {
		s.myArray.Append(data)
	}
}

这里我们加入数组和迭代器,将上节课所学知识更好的包装起来

2. 可完善内容

写完后发现有几个不足之处

  • 迭代器这里我们设置成外部可访问,不是很好,可以自己定义遍历方法来防止外部直接使用
  • capSize的定义,或许我们可以放在原先的数组里,并为其添加一个获取容量大小的方法会更加简洁明了
  • 等等......

你可能感兴趣的:(Go数据结构与算法小白入门,数据结构,开发语言,golang,后端)