简介

Go的标准包container中包含了常用的容器类型,包括conatiner/listcontainer/heapcontainer/ring。本篇介绍conatiner/list

conatiner/list实现了一个双向链表。使用起来与其他语言的动态列表非常相似,3秒钟便可入门。

3秒钟入门

package main

import (
    "container/list"
    "fmt"
)

func main() {
    nums := list.New()
    nums.PushBack(1)
    nums.PushBack(2)
    nums.PushBack(3)
    for e := nums.Front(); e != nil; e = e.Next() {
        fmt.Println(e.Value)
    }
}

包中有什么

包里只导出了两个类型和一个函数:

  • 表示列表的List类型
  • 表示列表元素的Element类型
  • 创建List的函数

container/list

// 表示双向列表
type List struct{ ... }

// 表示列表中的元素
type Element struct{ ... }

// 创建List
func New() *List

下面详细讲解该包的用法。

Element

先来看看Element类型:

container/list

type Element struct {
    Value interface{}  // 存储在该元素中的值
}

可以看到值的类型为 interface{},因此Element可以存储任何值。

创建List

使用New来创建List,函数原型如下:

container/list

func New() *List

示例:

coll := list.New()

添加元素

List导出了六个方法用于添加元素:

container/list

// 追加新元素到末尾,返回该元素指针
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

示例:

// 追加元素到末尾
coll.PushBack(1)
coll.PushBack("Gopher")

// 添加元素到开头
coll.PushFront("Cynhard")
two := coll.PushFront(2)

// 插入元素到two之前
before2 := coll.InsertBefore("Before2", two)

// 插入元素到two之后
after2 := coll.InsertAfter("After2", two)

coll2 := list.New()
coll2.PushBack(3)
coll2.PushFront("Tomcat")

// 追加另外一个列表到末尾
coll.PushBackList(coll2)

// 添加另外一个列表到开头
coll.PushFrontList(coll2)

应注意到一个列表中的元素的值的类型不必一致。

移动元素

List导出了四个方法用于移动元素:

container/list

// 移动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和mark都必须是l的内的元素,否则该函数不执行任何动作。

示例:

two := coll.PushFront(2)
before2 := coll.InsertBefore("Before2", two)
after2 := coll.InsertAfter("After2", two)

// 将before2移动到two的后面
coll.MoveAfter(before2, two)
// 将after2移动到two的前面
coll.MoveBefore(after2, two)
// 将before2移动到开头
coll.MoveToFront(before2)
// 将after2移动到末尾
coll.MoveToBack(after2)

访问元素

List导出了Back()和Front()返回结尾和开头元素:

container/list

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

示例:

fmt.Println(coll.Front().Value) // 打印开头元素的值
fmt.Println(coll.Back().Value) // 打印结尾元素的值

遍历列表

Element导出了两个方法Prev()和Next()用以访问前一个或后一个元素:

container/list

// 返回下一个元素,如果没有下一个元素,返回nil
func (e *Element) Next() *Element
// 返回前一个元素,如果没有前一个元素,返回nil
func (e *Element) Prev() *Element

示例:

// 顺序遍历
for e := coll.Front(); e != nil; e = e.Next() {
    fmt.Print(e.Value, " ")
}
fmt.Println()
// 逆序遍历
for e := coll.Back(); e != nil; e = e.Prev() {
    fmt.Print(e.Value, " ")
}
fmt.Println()

获取列表长度

container/list

func (l *List) Len() int

示例:

fmt.Println(coll.Len())

移除元素

container/list

// 移除e,返回e的值
func (l *List) Remove(e *Element) interface{}
// 清空列表
func (l *List) Init() *List

示例:

coll := list.New()
two := coll.PushFront(2)
coll.Remove(two) // 移除two
coll.Init()  // 清空列表

完整示例

package main

import (
    "container/list"
    "fmt"
)

func printList(coll *list.List) {
    for e := coll.Front(); e != nil; e = e.Next() {
        fmt.Print(e.Value, " ")
    }
    fmt.Println()
}

func printListR(coll *list.List) {
    for e := coll.Back(); e != nil; e = e.Prev() {
        fmt.Print(e.Value, " ")
    }
    fmt.Println()
}

func main() {
    coll := list.New()

    coll.PushBack(1)
    coll.PushBack("Gopher")

    coll.PushFront("Cynhard")
    two := coll.PushFront(2)

    before2 := coll.InsertBefore("Before2", two)
    after2 := coll.InsertAfter("After2", two)

    coll.MoveAfter(before2, two)
    coll.MoveBefore(after2, two)
    coll.MoveToFront(before2)
    coll.MoveToBack(after2)

    coll2 := list.New()
    coll2.PushBack(3)
    coll2.PushFront("Tomcat")

    coll.PushBackList(coll2)
    coll.PushFrontList(coll2)

    printList(coll)
    printListR(coll)

    fmt.Println(coll.Front().Value)
    fmt.Println(coll.Back().Value)

    fmt.Println(coll.Len())

    coll.Remove(two)

    printList(coll)

    coll.Init()
    printList(coll)
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐