Go学习笔记-链表

Go 语言的链表实现在其标准库的container/list代码包中。这个包包含了两个公开的程序实体:List和Element.
前者实现了一个双向链表(以下简称链表),而后者则代表了链表中元素的结构。

结构体类型的零值,都会拥有其特定结构,但没有初始化内容的缺省值。

var a [2]int  : 包含了两个0的整数数组;
var s []int   : 一个 []int类型的、值为nil的切片
var l list.list :长度为0的链表

func New() *List               新建一个链表,并初始化链表(调用Init方法初始化) 
func (l *List) Init() *List  初始化链表,或者清理链表。把链表的长度置为0。并将root的prev和next都指向自己
func (l *List) Len() int     返回链表的长度,其实就是直接返回其len属性,所以时间复杂度为O(1) 

func (l *List) MoveBefore(e, mark *Element) 把给定的元素移动到另一个元素的前面。
func (l *List) MoveAfter(e, mark *Element)  把给定的元素移动到另一个元素的后面。

func (l *List) MoveToFront(e *Element)         把给定的元素移动到链表的最前端。
func (l *List) MoveToBack(e *Element)         把给定的元素移动到链表的最后端。

func (l *List) Front() *Element             获取链表最前端元素
func (l *List) Back() *Element              获取链表最后的元素

func (l *List) InsertBefore(v interface{}, mark *Element) *Element 在指定元素之前插入新元素
func (l *List) InsertAfter(v interface{}, mark *Element) *Element  在指定元素之后插入新元素

func (l *List) PushFront(v interface{}) *Element 在链表最前端插入新元素
func (l *List) PushBack(v interface{}) *Element  在链表最后端插入新元素

func (l *List) Remove(e *Element) interface{}    如果e对于的链表是l,删除l中的元素e。返回的结果一定是e中的Value

“给定的元素”都是*Element类型的,该类型是Elemeent类型的指针类型,此类型的值就是元素的指针。

扫描二维码关注公众号,回复: 5373802 查看本文章


ring与list的区别:
1.Ring类型的数据结构仅由它自身即可代表,而List类型则需要由它以及Element类型联合表示。
2.一个Ring类型的值严格来讲,只代表了其所属的循环链表中的一个元素,而一个List类型的值则代表了一个完整的链表。
3.在创建并初始化一个Ring值的时候,我们可以指定它包含的元素的数量,但是对于一个List,循环链表一旦被创建,其长度是不可变的
4.仅通过var r ring.Ring语句声明的r将会是一个长度为1的循环链表,而List类型的零值则是一个长度为0的链表
5.Ring值的Len方法的算法复杂度是 O(N) 的,而List值的Len方法的算法复杂度则是 O(1) 的。

练习:

package main

import (
    "container/list"
    "fmt"
)

func main() {
    // 创建一个链表
    alist := list.New()

    fmt.Println("Size before : ", alist.Len())

    //向链表中添加元素  在list l的末尾插入值为v的元素,并返回该元素。
    alist.PushBack("a")
    alist.PushBack("b")
    alist.PushBack("c")

    fmt.Println("Size after insert(push): ", alist.Len())

    // 遍历
    for e := alist.Front(); e != nil; e = e.Next() {
        fmt.Println(e.Value.(string))
    }

    //移除元素
    alist.Remove(alist.Front())
    alist.Remove(alist.Front())
    alist.Remove(alist.Front())

    fmt.Println("Size after remove(pop) : ", alist.Len())

}

源码中,链表的结构和部分方法:

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

// Next returns the next list element or nil.
func (e *Element) Next() *Element {
    if p := e.next; e.list != nil && p != &e.list.root {
        return p
    }
    return nil
}

// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
    if p := e.prev; e.list != nil && p != &e.list.root {
        return p
    }
    return nil
}

// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List struct {
    root Element // sentinel list element, only &root, root.prev, and root.next are used
    len  int     // current list length excluding (this) sentinel element
}

// Init initializes or clears list l.
func (l *List) Init() *List {
    l.root.next = &l.root
    l.root.prev = &l.root
    l.len = 0
    return l
}

// New returns an initialized list.
func New() *List { return new(List).Init() }

// Len returns the number of elements of list l.
// The complexity is O(1).
func (l *List) Len() int { return l.len }

// Front returns the first element of list l or nil.
func (l *List) Front() *Element {
    if l.len == 0 {
        return nil
    }
    return l.root.next
}

// Back returns the last element of list l or nil.
func (l *List) Back() *Element {
    if l.len == 0 {
        return nil
    }
    return l.root.prev
}

// lazyInit lazily initializes a zero List value.
func (l *List) lazyInit() {
    if l.root.next == nil {
        l.Init()
    }
}

猜你喜欢

转载自blog.csdn.net/Linzhongyilisha/article/details/83180486
今日推荐