返回顶部
首页 > 资讯 > 后端开发 > GO >Go container包的介绍
  • 427
分享到

Go container包的介绍

GO 2022-06-07 20:06:38 427人浏览 八月长安
摘要

目录1.简介2.list2.1数据结构2.2插入元素3.ring3.1数据结构4.heap4.1数据结构1.简介 Container — 容器数据类型:该包实现了三个复杂的数

目录

1.简介

2.list

2.1数据结构

2.2插入元素

3.ring

3.1数据结构

4.heap

4.1数据结构

1.简介

Container — 容器数据类型:该包实现了三个复杂的数据结构:堆、链表、环

List
Go中对链表的实现,其中List:双向链表,Element:链表中的元素

Ring
:实现的是一个循环链表,也就是我们俗称的环

Heap
:Go中对堆的实现

2.list

简单实用:


func main()  {
 // 初始化双向链表
 l := list.New()
 // 链表头插入
 l.PushFront(1)
 // 链表尾插入
 l.PushBack(2)
 l.PushFront(3)
 // 从头开始遍历
 for head := l.Front();head != nil;head = head.Next() {
  fmt.Println(head.Value)
 }
}

方法列表:


type Element
    func (e *Element) Next() *Element                                   // 返回该元素的下一个元素,如果没有下一个元素则返回 nil
    func (e *Element) Prev() *Element                                   // 返回该元素的前一个元素,如果没有前一个元素则返回nil
type List                               
    func New() *List                                                    // 返回一个初始化的list
    func (l *List) Back() *Element                                      // 获取list l的最后一个元素
    func (l *List) Front() *Element                                     // 获取list l的第一个元素
    func (l *List) Init() *List                                         // list l 初始化或者清除 list l
    func (l *List) InsertAfter(v interface{}, mark *Element) *Element   // 在 list l 中元素 mark 之后插入一个值为 v 的元素,并返回该元素,如果 mark 不是list中元素,则 list 不改变
    func (l *List) InsertBefore(v interface{}, mark *Element) *Element  // 在 list l 中元素 mark 之前插入一个值为 v 的元素,并返回该元素,如果 mark 不是list中元素,则 list 不改变
    func (l *List) Len() int                                            // 获取 list l 的长度
    func (l *List) MoveAfter(e, mark *Element)                          // 将元素 e 移动到元素 mark 之后,如果元素e 或者 mark 不属于 list l,或者 e==mark,则 list l 不改变
    func (l *List) MoveBefore(e, mark *Element)                         // 将元素 e 移动到元素 mark 之前,如果元素e 或者 mark 不属于 list l,或者 e==mark,则 list l 不改变
    func (l *List) MoveToBack(e *Element)                               // 将元素 e 移动到 list l 的末尾,如果 e 不属于list l,则list不改变             
    func (l *List) MoveToFront(e *Element)                              // 将元素 e 移动到 list l 的首部,如果 e 不属于list l,则list不改变             
    func (l *List) PushBack(v interface{}) *Element                     // 在 list l 的末尾插入值为 v 的元素,并返回该元素              
    func (l *List) PushBackList(other *List)                            // 在 list l 的尾部插入另外一个 list,其中l 和 other 可以相等               
    func (l *List) PushFront(v interface{}) *Element                    // 在 list l 的首部插入值为 v 的元素,并返回该元素              
    func (l *List) PushFrontList(other *List)                           // 在 list l 的首部插入另外一个 list,其中 l 和 other 可以相等              
    func (l *List) Remove(e *Element) interface{}                       // 如果元素 e 属于list l,将其从 list 中删除,并返回元素 e 的值
2.1数据结构

节点定义:


type Element struct {
 // 后继指针,前向指针
 next, prev *Element
 // 链表指针,属于哪个链表
 list *List
 // 节点value
 Value interface{}
}

双向链表定义:


type List struct {
  // 根元素
 root Element // sentinel list element, only &root, root.prev, and root.next are used
 // 实际节点数量
  len  int     // current list length excluding (this) sentinel element
}

初始化:


// 通过工厂方法返回list指针
func New() *List { return new(List).Init() }
func (l *List) Init() *List {
 l.root.next = &l.root
 l.root.prev = &l.root
 l.len = 0
 return l
}

这里可以看到

root
节点作为一个根节点,不承担数据,也不是实际的链表节点,节点数量len没算上它,再初始化的时候,
root
节点会成为一个只有一个节点的环(前后指针都指向自己)

2.2插入元素

头插法:


func (l *List) Front() *Element {
 if l.len == 0 {
  return nil
 }
 return l.root.next
}
func (l *List) PushFront(v interface{}) *Element {
 l.lazyInit()
 return l.insertValue(v, &l.root)
}

尾插法:


func (l *List) Back() *Element {
 if l.len == 0 {
  return nil
 }
 return l.root.prev
}
func (l *List) PushBack(v interface{}) *Element {
 l.lazyInit()
 return l.insertValue(v, l.root.prev)
}

在指定元素后新增元素:


func (l *List) insert(e, at *Element) *Element {
 e.prev = at
 e.next = at.next
 e.prev.next = e
 e.next.prev = e
 e.list = l
 l.len++
 return e
}

这里有个延迟初始化的逻辑:

lazyInit
,把初始化操作延后,仅在实际需要的时候才进行


func (l *List) lazyInit() {
 if l.root.next == nil {
  l.Init()
 }
}

移除元素:


// remove 从双向链表中移除一个元素e,递减链表的长度,返回该元素e 
func (l *List) remove(e *Element) *Element {
  e.prev.next = e.next
  e.next.prev = e.prev
  e.next = nil // 防止内存泄漏
  e.prev = nil // 防止内存泄漏
  e.list = nil
  l.len --
  return e 
}
3.ring

Go中提供的ring是一个双向的循环链表,与list的区别在于没有表头和表尾,ring表头和表尾相连,构成一个环

使用demo:


func main()  {
 // 初始化3个元素的环,返回头节点
 r := ring.New(3)
 // 给环填充值
 for i := 1;i <= 3;i++{
  r.Value = i
  r = r.Next()
 }
 sum := 0
 // 对环的每个元素进行处理
 r.Do(func(i interface{}) {
  sum = i.(int) + sum
 })
 fmt.Println(sum)
}

方法列表:


type Ring
    func New(n int) *Ring  // 初始化环
    func (r *Ring) Do(f func(interface{}))  // 循环环进行操作
    func (r *Ring) Len() int // 环长度
    func (r *Ring) Link(s *Ring) *Ring // 连接两个环
    func (r *Ring) Move(n int) *Ring // 指针从当前元素开始向后移动或者向前(n 可以为负数)
    func (r *Ring) Next() *Ring // 当前元素的下个元素
    func (r *Ring) Prev() *Ring // 当前元素的上个元素
    func (r *Ring) Unlink(n int) *Ring // 从当前元素开始,删除 n 个元素
3.1数据结构

环节点数据结构:


type Ring struct {
 next, prev *Ring // 前继和后继指针
 Value      interface{} // for use by client; untouched by this library
}

初始化一个环:后继和前继指针都指向自己


func (r *Ring) init() *Ring {
 r.next = r
 r.prev = r
 return r
}

初始化指定数量个节点的环


func New(n int) *Ring {
 if n <= 0 {
  return nil
 }
 r := new(Ring)
 p := r
 for i := 1; i < n; i++ {
  p.next = &Ring{prev: p}
  p = p.next
 }
 p.next = r
 r.prev = p
 return r
}

遍历环,对个元素执行指定操作:


func (r *Ring) Do(f func(interface{})) {
 if r != nil {
  f(r.Value)
  for p := r.Next(); p != r; p = p.next {
   f(p.Value)
  }
 }
}
4.heap

Go中堆使用的数据结构是最小二叉树,即根节点比左边子树和右边子树的所有值都小

使用demo:需要实现

Interface
接口,go中堆都是实现这个接口,定义了排序,插入和删除方法


type Interface interface {
    sort.Interface
    Push(x interface{}) // add x as element Len()
    Pop() interface{}   // remove and return element Len() - 1.
}

实现接口:


// An IntHeap is a min-heap of ints.
type IntHeap []int
func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) {
 // Push and Pop use pointer receivers because they modify the slice's length,
 // not just its contents.
 *h = append(*h, x.(int))
}
func (h *IntHeap) Pop() interface{} {
 old := *h
 n := len(old)
 x := old[n-1]
 *h = old[0 : n-1]
 return x
}
// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func Example_intHeap() {
 h := &IntHeap{2, 1, 5}
 heap.Init(h)
 heap.Push(h, 3)
 fmt.Printf("minimum: %d\n", (*h)[0])
 for h.Len() > 0 {
  fmt.Printf("%d ", heap.Pop(h))
 }
 // Output:
 // minimum: 1
 // 1 2 3 5
}
4.1数据结构

上浮:


func Push(h Interface, x interface{}) {
 h.Push(x)
 up(h, h.Len()-1)
}
func up(h Interface, j int) {
 for {
  i := (j - 1) / 2 // parent
  if i == j || !h.Less(j, i) {
   break
  }
  h.Swap(i, j)
  j = i
 }
}

下沉:


func Pop(h Interface) interface{} {
 n := h.Len() - 1
 h.Swap(0, n)
 down(h, 0, n)
 return h.Pop()
}
func down(h Interface, i0, n int) bool {
 i := i0
 for {
  j1 := 2*i + 1
  if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
   break
  }
  j := j1 // left child
  if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
   j = j2 // = 2*i + 2  // right child
  }
  if !h.Less(j, i) {
   break
  }
  h.Swap(i, j)
  i = j
 }
 return i > i0
}

到此这篇关于Go container包的介绍的文章就介绍到这了,更多相关Go container包内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


您可能感兴趣的文档:

--结束END--

本文标题: Go container包的介绍

本文链接: https://lsjlt.com/news/30729.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go container包的介绍
    目录1.简介2.list2.1数据结构2.2插入元素3.ring3.1数据结构4.heap4.1数据结构1.简介 Container — 容器数据类型:该包实现了三个复杂的数...
    99+
    2022-06-07
    GO
  • Go container包怎么使用
    这篇文章主要讲解了“Go container包怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go container包怎么使用”吧!1.简介Container —...
    99+
    2023-06-22
  • linux内核编程container of()函数介绍
    前言 在linux 内核编程中,会经常见到一个宏函数container_of(ptr,type,member), 但是当你通过追踪源码时,像我们这样的一般人就会绝望了(这一堆都是什么呀? 函数还可以这样定义??? 怎...
    99+
    2022-06-03
    linux container of()函数 container_of函数
  • Node.js的包详细介绍
    在Node.js语言中,包和模块并没有本质的不同,包是在模块的基础上更深一步的抽象,包将某个独立的功能封装起来,用于发布、更新、依赖管理和进行版本控制。Node.js根据CommonJS规范实现了包机制,开...
    99+
    2022-06-04
    详细介绍 Node js
  • java的Guava工具包介绍
    集合 普通集合 List<String> list = Lists.newArrayList(); Set<String> set = Sets.newH...
    99+
    2024-04-02
  • JavaScript闭包的简单介绍
    本篇内容主要讲解“JavaScript闭包的简单介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript闭包的简单介绍”吧!什么是JS闭包?先看一...
    99+
    2024-04-02
  • Python闭包技巧介绍
    目录1.闭包:用函数代替类2.访问定义在闭包的内的变量1.闭包:用函数代替类 有时我们会定义只有一个方法(除了__init__()之外)的类,而这种类可以通过使用闭包(closur...
    99+
    2024-04-02
  • Linux的包管理工具介绍
     概述:     本章内容:软件的运行环境,软件包基础,rpm包管理,yum管理,定制yum仓库,编译安装一、软件运行环境  1.API:Appl...
    99+
    2024-04-02
  • GoLangcontext包的使用方法介绍
    目录背景简介主要方法获得顶级上下文当前协程上下文的操作创建下级协程的Context场景示例背景 在父子协程协作过程中, 父协程需要给子协程传递信息, 子协程依据父协程传递的信息来决定...
    99+
    2023-03-15
    Go context Go context包 GoLang context
  • Go中Sync.Cond的介绍和使用
    本篇内容介绍了“Go中Sync.Cond的介绍和使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. 程序中的通信方式GO语言中有句名言:...
    99+
    2023-06-15
  • android SDk中常用的java包介绍
    下面是android SDK中API中的主要java包的功能简介:  代码如下:android.app :提供高层的程序模型、提供基本的运行环境android.c...
    99+
    2022-06-06
    java包 JAVA sdk Android
  • Golang常用包使用介绍
    目录sync包锁线程监听WaitGroup池Poolencoding/binary包单数值转换多数值转换encoding/gob包hash/crc32包sync包 常用的有3个功能 ...
    99+
    2024-04-02
  • 解决golang中container/list包中的坑
    golang中list包用法可以参看这篇文章 但是list包中大部分对于e *Element进行操作的元素都可能会导致程序崩溃,其根本原因是e是一个Element类型的指针,当然其也...
    99+
    2024-04-02
  • Go语言指针的详细介绍
    本篇内容介绍了“Go语言指针的详细介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Go语言为程序员提供了...
    99+
    2024-04-02
  • Go语言中DateTime的用法介绍
    一、基本使用 ①从属于time这个包 ②一般使用都是使用 time.Time 这个类型表示时间 ,time包中还有一些常量,源码如下 // Common durations. The...
    99+
    2024-04-02
  • Go语言中的Beego框架介绍
    Beego是一个基于MVC架构的Go语言Web框架,它提供了一整套的解决方案来简化Web应用程序的开发。Beego内置了很多功能模块,如路由、ORM、Session等,同时也提供了很多...
    99+
    2024-04-02
  • Go GORM 事务详细介绍
    目录禁用默认事务事务嵌套事务手动事务一个特殊的示例SavePoint、RollbackTo禁用默认事务 为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果...
    99+
    2024-04-02
  • RPM包知识点详细介绍
    这篇文章主要介绍“RPM包知识点详细介绍”,在日常操作中,相信很多人在RPM包知识点详细介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”RPM包知识点详细介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-16
  • Go语言中log日志库的介绍
    目录一、标准库log介绍1、使用Logger2、配置logger 2.1、标准logger的配置二、自定义日志库 1、需要满足的需求2、了解下runtime包3、...
    99+
    2024-04-02
  • Go 语言入门之Go 计时器介绍
    目录引言Go 的计时器Ticker 计时器是如何工作的?Ticker 使用方式总结引言 一般来说,很多时候我们面临这样一种情况,即我们需要运行时间记录器,它不断向我们显示当前时...
    99+
    2022-06-07
    GO 计时器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作