Go语言 标准容器源码分析


类似于Java的集合:list,map,set等,Go语言中也提供了类似的标准容器,在标准包container包含了conatiner/list,container/heap,container/ring三种标准容器。

(1)conatiner/list 容器
在conatiner/list源码包中提供了相关的示例,比如下面这个示例

package list_test

import (
   "container/list"
   "fmt"
)

func Example() {
   // 创建一个新list并在其中放入一些数字。
   l := list.New()
   e4 := l.PushBack(4)
   e1 := l.PushFront(1)
   l.InsertBefore(3, e4)
   l.InsertAfter(2, e1)

   // Iterate through list and print its contents.
   for e := l.Front(); e != nil; e = e.Next() {
      fmt.Println(e.Value)
   }
}

list是一个双向的链表,可以添加类型不一的元素进来,它的相关类型说明如下所示:

// 表示列表中的元素
type Element struct {
    //双向链接元素列表中的下一个和前一个指针。
   next, prev *Element
   //此元素所属的列表。
   list *List
   // 使用此元素存储的值。
   Value interface{}
}

// List表示双向链表。
// List的零值是一个可供使用的空列表。
type List struct {
   root Element // //列出代表列表元素,仅使用&root,root.prev和root.next
   len  int     //当前列表长度不包括(this)sentinel元素
}

初始化函数说明如下所示:

//New返回初始化列表。
func New() *List { return new(List).Init() }

// Init初始化或清除列表l。
func (l *List) Init() *List {
   l.root.next = &l.root
   l.root.prev = &l.root
   l.len = 0
   return l
}

添加元素函数说明:可以添加类型不一的元素进来:

// 追加新元素到末尾,返回该元素指针
func (l *List) PushBack(v interface{}) *Element
// 追加另一个列表到末尾
func (l *List) PushBackList(other *List)
// 添加新元素到开头,返回该元素指针
func (l *List) PushFront(v interface{}) *Element
// 添加另一个列表到开头
func (l *List) PushFrontList(other *List)
// 在mark后面插入新元素,返回新元素指针
func (l *List) InsertAfter(v interface{}, mark *Element) *Element
// 在mark前插入新元素,返回新元素指针
func (l *List) InsertBefore(v interface{}, mark *Element) *Element

移除元素函数说明:e和mark都必须是l的内的元素,否则该函数不执行任何动作

// 移动e到mark之后
func (l *List) MoveAfter(e, mark *Element)
// 移动e到mark之前
func (l *List) MoveBefore(e, mark *Element)
// 移动e到末尾
func (l *List) MoveToBack(e *Element)
// 移动e到开头
func (l *List) MoveToFront(e *Element)
// 移除e,返回e的值
func (l *List) Remove(e *Element) interface{}

访问元素函数说明:

// 返回结尾元素
func (l *List) Back() *Element
// 返回开头元素
func (l *List) Front() *Element

遍历函数说明:

// Len返回列表l的元素数。
//复杂性是O(1)。
func (l *List) Len() int { return l.len }

// Next返回下一个列表元素或nil。
func (e *Element) Next() *Element

// Prev返回上一个列表元素或nil。
func (e *Element) Prev() *Element

(2)conatiner/ ring 容器
关于ring 容器的函数说明与结构如下所示:

// Ring是循环列表或循环的元素。
type Ring struct {
    Value interface{} // 类型为interface{},因此可以接受任意类型
}

// 创建一个长度为n的环形链表
func New(n int) *Ring

// 针对环形链表中的每一个元素x进行f(x)操作
func (r *Ring) Do(f func(interface{}))

// 获取环形链表长度
func (r *Ring) Len() int

// 如果r和s在同一环形链表中,则删除r和s之间的元素
// 被删除的元素组成一个新的环形链表,返回值为该环形链表的指针(即删除前,r->Next()表示的元素)
// 如果r和s不在同一个环形链表中,则将s插入到r后面,返回值为 插入s后,s最后一个元素的下一个元素(即插入前,r->Next()表示的元素)
func (r *Ring) Link(s *Ring) *Ring

// 移动 n % r.Len() 个位置,n正负均可
func (r *Ring) Move(n int) *Ring

// 返回下一个元素
func (r *Ring) Next() *Ring

// 返回前一个元素
func (r *Ring) Prev() *Ring

// 删除r后面的 n % r.Len() 个元素
func (r *Ring) Unlink(n int) *Ring

(3)conatiner/ heap 容器
conatiner/ heap 容器仅仅提供了最小堆的操作,然后由我们自己实现堆的数据结构(必须满足heap定义的接口),再利用heap包提供了一个heap.Interface接口做桥梁跟堆的操作搭上关系。

堆数据结构满足的接口定义:

type Interface interface {
   sort.Interface
   Push(x interface{}) // 将x添加为元素Len()
   Pop() interface{}   // 移除并返回元素的Len() - 1
}

而 sort.Interface 的接口定义如下:

type Interface interface {
   // Len is the number of elements in the collection.
   Len() int
   // Less reports whether the element with
   // index i should sort before the element with index j.
   Less(i, j int) bool
   // Swap swaps the elements with indexes i and j.
   Swap(i, j int)
}

也就是说,如果我们让堆的数据结构与heap提供的堆操作搭上关系,就必须实现上面的五个方法。

heap包中还提供了下面几个函数的实现:

//必须先初始化堆,然后才能使用任何堆操作。 Init对于堆不变量是幂等的,并且可以在堆不变量可能被无效时被调用。
//其复杂度为O(n),其中n = h.Len()。
func Init(h Interface)

// Push将元素x推送到堆上。 复杂度为O(log(n)),其中n = h.Len()。
func Push(h Interface, x interface{})

// Pop从堆中删除最小元素(根据Less)并返回它。 复杂度为O(log(n)),其中n = h.Len()。
//相当于Remove(h,0)。
func Pop(h Interface) interface{} 

// Remove从堆中删除索引i处的元素。
//复杂度为O(log(n)),其中n = h.Len()。
func Remove(h Interface, i int)

//修复在索引i处的元素更改其值后重新建立堆排序。
//在索引i处更改元素的值,然后调用Fix,相当于调用Remove(h,i),然后调用新值,相当于便宜。
//复杂度为O(log(n)),其中n = h.Len()。
func Fix(h Interface, i int)

func up(h Interface, j int) 

func down(h Interface, i0, n int) bool

你可能感兴趣的:(Go语言 标准容器源码分析)