Golang数据结构 - 2 - 栈

monigo · · 1189 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

上一部分中,我们用Go实现了最常用的数据结构-数组,并实现了数组的添加元素、删除元素、数组遍历、数组排序和数组查找等功能。

在数组中我们可以实现任意位置的添加或删除元素,但是在某些场景中,需要我们对数据的添加或删除进行进一步的限制,于是就有了栈和队列。本章将使用Go来实现栈和栈的一些基本功能。

栈是一种运算受限的线性表,对栈中数据进行操作的时候需要遵循后进先出(LIFO)原则。在栈中对元素进行入栈或出栈操作的一端叫作栈顶,另一端则为栈底

本章中将基于Golang切片和链表两种实现方法来实现栈。

栈定义

首先定义栈接口,其中包含以下方法:

  • Push(e ...Element):添加若干元素到栈顶
  • Pop() Element:弹出一个栈顶元素
  • Peek() Element:返回栈顶元素,不弹出
  • Empty() bool: 返回张是否为空
  • Clear():清空栈内所有元素
  • Size() int:返回栈的大小

代码如下

type Element interface { } type Interface interface { // 添加若干元素到栈顶 Push(e ...Element) // 弹出栈顶元素 Pop() Element // 只返回不弹出栈顶元素 Peek() Element // 栈是否为空 Empty() bool // 清空栈元素 Clear() // 返回栈的大小 Size() int } 

向栈顶添加元素

  1. 数组切片实现
// 向栈顶添加元素 func (s *ArrayStack) Push(e ...Element) { *s = append(*s, e...) } 
  1. 链表实现
// 向栈顶添加元素 func (s *LinkedStack) Push(e ...Element) { for _, v := range e { n := s.Head.Next s.Head.Next = &node{ Value: v, Next: n, } s.size++ } } 

元素出栈

  1. 数组切片实现
// 弹出栈顶元素 func (s *ArrayStack) Pop() Element { if s.Empty() { return nil } ln := len(*s) // 获取栈顶元素 val := (*s)[ln-1] // 弹出栈顶元素 *s = (*s)[:ln-1] return val } 
  1. 链表实现
// 弹出栈顶元素 func (s *LinkedStack) Pop() Element { if s.Empty() { return nil } first := s.Head.Next s.Head.Next = first.Next s.size-- return first.Value } 

查看栈顶元素

  1. 数组切片实现
// 查看栈顶元素 func (s *ArrayStack) Peek() Element { if s.Empty() { return nil } return (*s)[len(*s)-1] } 
  1. 链表实现
// 查看栈顶元素 func (s *LinkedStack) Peek() Element { if s.Empty() { return nil } return s.Head.Next.Value } 

查看栈大小

  1. 数组切片实现
// 返回栈大小 func (s *ArrayStack) Size() int { return len(*s) } 
  1. 链表实现
// 返回栈大小 // 由于使用了一个计数器,直接返回即可,时间复杂度O(1) func (s *LinkedStack) Size() int { return s.size } 

检查栈是否为空

  1. 数组切片实现
// 栈是否为空 func (s *ArrayStack) Empty() bool { return s.Size() == 0 } 
  1. 链表实现
// 栈是否为空 func (s *LinkedStack) Empty() bool { return s.Head.Next == nil } 

清空栈

  1. 数组切片实现
// 清空栈 func (s *ArrayStack) Clear() { *s = ArrayStack{} } 
  1. 链表实现
// 清空栈 func (s *LinkedStack) Clear() { s.Head.Next = nil } 

完整实现代码

package main import "fmt" type Element interface { } type Interface interface { // 添加若干元素到栈顶 Push(e ...Element) // 弹出栈顶元素 Pop() Element // 只返回不弹出栈顶元素 Peek() Element // 栈是否为空 Empty() bool // 清空栈元素 Clear() // 返回栈的大小 Size() int } type ArrayStack []Element // 向栈顶添加元素 func (s *ArrayStack) Push(e ...Element) { *s = append(*s, e...) } // 弹出栈顶元素 func (s *ArrayStack) Pop() Element { if s.Empty() { return nil } ln := len(*s) // 获取栈顶元素 val := (*s)[ln-1] // 弹出栈顶元素 *s = (*s)[:ln-1] return val } // 查看栈顶元素 func (s *ArrayStack) Peek() Element { if s.Empty() { return nil } return (*s)[len(*s)-1] } // 栈是否为空 func (s *ArrayStack) Empty() bool { return s.Size() == 0 } // 清空栈 func (s *ArrayStack) Clear() { *s = ArrayStack{} } // 返回栈大小 func (s *ArrayStack) Size() int { return len(*s) } // 基于Slice实现构造栈 func NewArrayStack() Interface { return &ArrayStack{} } // 链表实现栈节点定义 type node struct { Value Element Next *node } // 链表实现栈 type LinkedStack struct { Head *node size int } // 向栈顶添加元素 func (s *LinkedStack) Push(e ...Element) { for _, v := range e { n := s.Head.Next s.Head.Next = &node{ Value: v, Next: n, } s.size++ } } // 弹出栈顶元素 func (s *LinkedStack) Pop() Element { if s.Empty() { return nil } first := s.Head.Next s.Head.Next = first.Next s.size-- return first.Value } // 查看栈顶元素 func (s *LinkedStack) Peek() Element { if s.Empty() { return nil } return s.Head.Next.Value } // 栈是否为空 func (s *LinkedStack) Empty() bool { return s.Head.Next == nil } // 清空栈 func (s *LinkedStack) Clear() { s.Head.Next = nil } // 返回栈大小 // 由于使用了一个计数器,直接返回即可,时间复杂度O(1) func (s *LinkedStack) Size() int { return s.size } // 链表实现栈构造 func NewLinkedStack() Interface { return &LinkedStack{ Head: &node{}, } } func main() { //s := NewStack() s := NewLinkedStack() fmt.Println("Empty", s.Empty()) s.Push(1, 2, 3, 4, 5, 6, 7, 8, 9) fmt.Println("Push 1,2,3,4,5") fmt.Println("Size:", s.Size()) fmt.Println("Peek:", s.Peek()) fmt.Println("Pop:", s.Pop(), s.Pop(), s.Pop()) s.Clear() fmt.Println("Clear Empty:", s.Empty()) } 

运行结果

Empty true Push 1,2,3,4,5 Size: 9 Peek: 9 Pop: 9 8 7 Clear Empty: true Process finished with exit code 0 

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:monigo

查看原文:Golang数据结构 - 2 - 栈

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1189 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传