go源码-容器-集合List

93 阅读2分钟

List底层数据结构

底层使用双向链表实现。头尾相接形成环。源码位于src\container\list\list.go

type List struct {  
    root Element 
    len int 
}  
func (l *List) Init() *List {  
    l.root.next = &l.root  
    l.root.prev = &l.root  
    l.len = 0  
    return l  
}

从源码中可以看到List包含了长度len和根节点root,rootElement类型,接着看一下Element的源码:

type Element struct {  
    next, prev *Element  
    list *List  
    Value any  
}

Element包含了指针nextpre,对象list,具体的值Value。个别场景,我们需要知道Element所在的链表的时候,可以利用list属性。list这个属性在插入的时候被赋值。如下:

func (l *List) insert(e, at *Element) *Element {  
    e.prev = at  
    e.next = at.next  
    e.prev.next = e  
    e.next.prev = e  
    e.list = l  
    l.len++  
    return e  
}

懒加载

List也支持懒加载,可以直接通过new创建List对象,push的时候才创建List的内部细节,如下:

func (l *List) lazyInit() {  
    if l.root.next == nil {  
        l.Init()  
    }  
}

func (l *List) PushFront(v any) *Element {  
    l.lazyInit()  
    return l.insertValue(v, &l.root)  
}

官方接口

官方提供了很多接口对List进行操作:

  • Remove(*Element)Val: 将指定的ElementList中剔除(Element在List里)
  • Back()*Element:返回最后一个元素
  • Front()*Element:返回第一个元素
  • lazyInit():懒加载,如果List没有初始化,则调用初始化函数Init()
  • insert(e,at *Element):将元素e添加到at元素的后面。后续的push类型的函数都基于insert
  • insertValue(val any,at*Element):将值val包装成Element并插入到at的后面
  • move(e,at *Element):将e挪到at的后面
  • PushFront(v any)*Element: 将v push到最前面
  • PushBack(v any)*Element: 将v push到最后面
  • InsertBefor(v any,mark *Element):将v包装成Element,插入到mark之前,前提mart是当前List的元素
  • InsertAfter(v any,mark *Element):将v包装成Element,插入到mark之后,前提mart是当前List的元素
  • MoveToFront(e *Element):将e挪到最前面。
  • MoveToBack(e *Element):将e挪到最后面。
  • MoveBefore(e,at *Element):将e挪到at之前。
  • MoveAfter(e,at *Element):将e挪到at之后。
  • PushBackList(other *List):遍历other,将其元素全部顺序追加到当前List的末尾。
  • PushFrontList(other *List):遍历other,将其元素全部顺序追加到当前List的前面。(PushBackList,PushFrontList中,从other中获取插入当前List的Element是一个新对象)