container包中有三个数据结构:heap(堆)、list(链表)、ring(环)
Package list
import "container/list"
list包实现了双向链表,要遍历一个链表:
for e := l.Front(); e != nil; e = e.Next() { // do something with e.Value }
type Element
Element代表的是链表节点
type Element struct { next, prev *Element // next, prev 分别指向下一个和上一个节点 list *List // list 为元素所在链表 Value interface{} // Value 为链表节点存储元素 }
Next和Prev方法
// Next 返回链表下一个元素或nil func (e *Element) Next() *Element { if p := e.next; e.list != nil && p != &e.list.root { return p } return nil } // Prev 返回链表上一个元素或nil func (e *Element) Prev() *Element { if p := e.prev; e.list != nil && p != &e.list.root { return p } return nil }
type List
List代表一个双向链表。List零值为一个空的、可用的链表。
type List struct { root Element // root 作为哨兵节点 len int // len 是List长度,包括root }
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 } // 返回链表长度 func (l *List) Len() int { return l.len }
list中包含的方法包括:
链表功能的基本实现
//延迟初始化 func (l *List) lazyInit() { if l.root.next == nil { l.Init() } } //返回list头节点元素 func (l *List) Front() *Element {} //返回list尾节点元素 func (l *List) Back() *Element {} //将一个值为v的新元素插入链表的第一个位置,返回生成的新元素 func (l *List) PushFront(v interface{}) *Element {} //创建链表other的拷贝,并将拷贝的最后一个位置连接到list的第一个位置 func (l *List) PushFrontList(other *List) {} //将一个值为v的新元素插入链表的第一个位置,返回生成的新元素 func (l *List) PushBack(v interface{}) *Element {} //创建链表other的拷贝,并将拷贝的第一个位置连接到list的最后一个位置 func (l *List) PushBackList(other *List) {} //将一个值为v的新元素插入到mark前面,并返回生成的新元素。如果mark不是l的元素,l不会被修改 func (l *List) InsertBefore(v interface{}, mark *Element) *Element {} //将一个值为v的新元素插入到mark后面,并返回新生成的元素。如果mark不是l的元素,l不会被修改 func (l *List) InsertAfter(v interface{}, mark *Element) *Element {} //将元素e移动到链表的第一个位置,如果e不是l的元素,l不会被修改 func (l *List) MoveToFront(e *Element) {} //将元素e移动到链表的最后一个位置,如果e不是l的元素,l不会被修改 func (l *List) MoveToBack(e *Element) {} //将元素e移动到mark的前面。如果e或mark不是l的元素,或者e==mark,l不会被修改 func (l *List) MoveBefore(e, mark *Element) {} //将元素e移动到mark的后面。如果e或mark不是l的元素,或者e==mark,l不会被修改 func (l *List) MoveAfter(e, mark *Element) {} //删除链表中的元素e,并返回e.Value func (l *List) Remove(e *Element) interface{} {}
container/list 标准库中代码实现巧妙,包括延迟初始化、封装设计等技巧,对小白(like me)有很好的借鉴意义。
这里摘出来几个片段
Remove实现了对内部remove的封装
func (l *List) remove(e *Element) *Element { e.prev.next = e.next e.next.prev = e.prev e.next = nil // avoid memory leaks e.prev = nil // avoid memory leaks e.list = nil l.len-- return e } func (l *List) Remove(e *Element) interface{} { if e.list == l { l.remove(e) } return e.Value }
MoveBefore和PushBackList都是对基本操作的调用
func (l *List) MoveBefore(e, mark *Element) { if e.list != l || e == mark || mark.list != l { return } l.insert(l.remove(e), mark.prev) } func (l *List) PushBackList(other *List) { l.lazyInit() for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { l.insertValue(e.Value, l.root.prev) } }
list包使用示例
其中使用几个代表性方法
package main import ( "container/list" "fmt" ) func main() { l := list.New() l.PushFront(1) // 1 l.PushBack(2) // 1->2 fmt.Println(l.Front().Value) // 1 fmt.Println(l.Back().Value) // 2 other := list.New() other.PushFront(3) other.PushBack(4) l.PushFrontList(other) // 3->4->1->2 fmt.Println(l.Front().Value) fmt.Println(l.Back().Value) fmt.Println(l.Len()) l.Remove(l.Front().Next()) // 3->1->2 fmt.Println(l.Len()) for v := l.Front(); v != nil; v = v.Next() { fmt.Printf("%d ", v.Value) } fmt.Printf("\n") }