go container/list 源码阅读

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--
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值