Golang数据结构 - 2 - 栈

栏目: Go · 发布时间: 4年前

内容简介:在在数组中我们可以实现任意位置的添加或删除元素,但是在某些场景中,需要我们对数据的添加或删除进行进一步的限制,于是就有了栈和队列。本章将使用Go来实现栈和栈的一些基本功能。栈是一种运算受限的线性表,对栈中数据进行操作的时候需要遵循后进先出(LIFO)原则。在栈中对元素进行入栈或出栈操作的一端叫作

上一部分 中,我们用 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

以上所述就是小编给大家介绍的《Golang数据结构 - 2 - 栈》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

闪魂FLASH8网站建设实录

闪魂FLASH8网站建设实录

马谧铤 / 中国林业 / 2006-7 / 46.00元

《闪魂FLASH8网站建设实录》旨在提供以Flash(Flash 8.0为创作工具)为技术核心的整套互动网站的开发思路,其中包括了网站策划、平面设计、程序设计等实用的互联网应用技术。内容包括Photoshop CS2设计,FIash 8创作和ActionScript应用程序开发的操作流程。在技术学习的过程中.大家还将体会到顶级互动网站设计、网站建设的设计流程和思路。《闪魂FLASH8网站建设实录》......一起来看看 《闪魂FLASH8网站建设实录》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具