go container/list 实现了双向循环链表。
源码地址:go/list.go at master · golang/go · GitHub
一 使用方法
func Example() {
// Create a new list and put some numbers in it.
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)
}
// Output:
// 1
// 2
// 3
// 4
}
list 暴露的接口
// 初始化list
func (l *List) Init() *List { }
// 新建一个list
func New() *List { return new(List).Init() }
//返回list 的长度
func (l *List) Len() int { return l.len }
//返回list 的第一个元素 list空时 返回nil
func (l *List) Front() *Element {}
// 返回list的最后一个元素
func (l *List) Back() *Element {}
//移除指定元素 并返回益处的元素
func (l *List) Remove(e *Element) any {}
//添加元素到列表的头部
func (l *List) PushFront(v any) *Element {}
// 添加元素到列表的尾部
func (l *List) PushBack(v any) *Element {}
//在指定元素前,插入新的值
func (l *List) InsertBefore(v any, mark *Element) *Element {}
//在指定元素后,插入新的值
func (l *List) InsertAfter(v any, mark *Element) *Element {}
//将指定元素移动到列表的头部
func (l *List) MoveToFront(e *Element) {}
//将指定元素移动到列表的尾部
func (l *List) MoveToBack(e *Element) {}
//将指定元素移动到某个元素前面
func (l *List) MoveBefore(e, mark *Element) {}
//将指定元素移动到某个元素后面
func (l *List) MoveAfter(e, mark *Element) {}
//合并两个list
func (l *List) PushBackList(other *List) {}
//合并两个list
func (l *List) PushFrontList(other *List) {}
二 源码实现
1.Element结构体
Element 用来存储链表的值。
// Element is an element of a linked list.
type Element struct {
next, prev *Element //分别指向链表的后继和前驱节点
list *List //指向链表
Value any //元素值
}
//返回元素的后继节点
func (e *Element) Next() *Element {}
//返回元素的前驱节点
func (e *Element) Prev() *Element {}
2.list结构体
type List struct {
root Element // 链表的哨兵,不用来存储实际节点。用来记录链表的头和尾
len int // 记录链表的长度
}
3. 在链表的尾部追加元素
// 在链表的尾部插入一个新的元素
func (l *List) PushBack(v any) *Element {
l.lazyInit()
//l.root.prev 指向链表的尾部
return l.insertValue(v, l.root.prev)
}
func (l *List) insertValue(v any, at *Element) *Element {
return l.insert(&Element{Value: v}, at)
}
// at 元素后插入元素 e
func (l *List) insert(e, at *Element) *Element {
e.prev = at //e 前驱指向 at
e.next = at.next //e 后继指向 at的后继
e.prev.next = e
e.next.prev = e
e.list = l //e归属于链表l
l.len++ //链表长度+1
return e
}
4. 删除元素
func (l *List) Remove(e *Element) any {
//判断元素 e是否属于链表 l
if e.list == l {
l.remove(e)
}
return e.Value
}
//
func (l *List) remove(e *Element) {
//将e从链表中移除
e.prev.next = e.next //e
e.next.prev = e.prev
//释放元素e
e.next = nil
e.prev = nil
e.list = nil
//链表长度-1
l.len--
}