blog/数据结构/使用go实现链栈.md

124 lines
2.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 使用go实现链栈
tags: go,数据结构,链栈
categories: 数据结构
date: 2022-01-09 10:28:29
---
# 栈的定义
栈是一种先进后出的数据结构,日常使用较为广泛,可以将其比喻成一个瓶子,先放进去的东西掉在了最下面,所以后放出来,栈一般只提供了两种操作方式,分别为入栈和出栈。栈分为链栈和顺序栈,顺序栈使用数组存储数据,链栈采用单链表村粗数据,我们今天是实现的链栈。
## 结构定义
```go
type Stack struct {
data interface{}
next *Stack
size int
sync.Mutex
}
```
data对应存储数据next是一个实例指针指向下面的一个元素size用来存储栈的大小其实可有可无sync.Mutex是解决并发操作的问题。
## 初始化栈
```go
func newStack() *Stack {
s := new(Stack)
s.next = nil
s.size = 0
return s
}
```
首先创建一个Stack对象将其next指针域置为nilsize置为0.
# 栈的相关操作
## 入栈
```go
func (s *Stack) push(element interface{}) {
s2 := new(Stack)
s2.next = s.next
s2.data = element
s.Lock()
s.size ++
s.next = s2
s.Unlock()
}
```
入栈首先创建一个新的节点然后将节点的指针指向头节点的指向然后为该节点赋值然后操纵头节点之前应该上锁将头节点的size加一同时头节点的指针指向新创建的节点最后取消锁。
## 出栈
```go
func (s *Stack) pop() interface{} {
if s.next == nil {
return nil
}
node := s.next
s.Lock()
s.size --
s.next = node.next
s.Unlock()
return node.data
}
```
出栈首先判断头节点的指针是否为nil,若为nil则代表栈内没有元素返回nil值然后将栈顶节点取出来然后将头节点的size减一同时将头节点的指针域指向栈顶节点的下一节点最后返回栈顶节点的值。
## 获取栈顶节点的值
```go
func (s *Stack) getTop() interface{} {
if s.next == nil {
return nil
}
return s.next.data
}
```
和出栈不一样的地方是,该方法只获取栈顶节点的值,不会删除栈顶节点。
## 全部出栈转为数组
```go
func (s *Stack) toArray() []interface{} {
array:= make([]interface{}, s.size)
length := s.size
for i := 0; i < length; i++ {
array[i] = s.pop()
}
return array
}
```
其中要将s.size单独取出来因为在循环过程中出栈s.size的值会发生改变。
# 测试
```go
func main() {
stack := newStack()
stack.push(1)
stack.push(2)
stack.push(3)
stack.push(1)
stack.push(4)
fmt.Println(stack.pop())
fmt.Println(stack.pop())
fmt.Println("栈的剩余元素个数:",stack.size)
fmt.Println(stack.toArray())
}
// 4
// 1
// 栈的剩余元素个数: 3
// [3 2 1]
```
## 个人博客地址:<https://vtsqr.xyz>