最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

go语言list表

来源:博客园

在go中的list表属于双向链表,表头部的prev和尾部的next同时指向一个相同的地址,从而实现了一个环。list的零值是一个准备使用的空列表。


(资料图片仅供参考)

源码:https://cs.opensource.google/go/go/+/refs/tags/go1.20.5:src/container/list/list.go

document:https://pkg.go.dev/container/list#pkg-overview

要使用list需要从container包引入。

list的方法

Next() : 返回下一个元素或nil

Prev(): 返回上一个元素或nil

Back(): 返回列表的最后一个元素,如果列表为空,则返回nil

Front(): 返回列表的首个元素,如果列表为空,则返回nil

Init(): 初始化或清空列表

InsertAfter(): 在某指定元素后插入

InsertBefore(): 在某指定元素前插入

Len(): 返回元素的个数,时间复杂度是O(1)

MoveToBack()、MoveToFront():将list中的某个元素移动到尾部/头部。如果元素不属于列表中的,则不会修改,元素必须不为nil。

MoveAfter(e,mark)、MoveBefore(e,mark): 将元素e移动到mark后面/前面,如果元素e或mark不属于list中的元素,或者e==mark,则不修改;e和mark不能是nil

PushBack()、PushFront()、Remove()见名知意

PushFrontList()、PushBackList(): 在列表的首部/尾部插入另外一个列表,他们不能为空。

方法示例:

package mainimport (    "container/list"    "fmt")func main() {    s := make([]int, 5)    l := list.New()    l2 := list.New().Init()    fmt.Printf("%T %+[1]v %p\n", l, &l)    fmt.Printf("%T %+[1]v %p\n", l2, &l2)    l2.PushBack("gopher")    l2.PushBack("come on")    l.PushBack(2)    l.PushFront("first")    l.PushBack("你好吗")    e := l.Front().Next()    l.InsertAfter("c", e)    l.InsertBefore(3.14, e)    l.InsertBefore(s, e)    l.PushBack("last")    l.PushBackList(l2)                                    // 将l2列表尾部加入到l列表中    e1 := l.Back().Prev().Prev()                          // 获取尾部的上一个的上一个元素    l.MoveToBack(e1)                                      // 将“last”移动到尾部    l.MoveAfter(l.Back().Prev().Prev(), l.Front().Next()) // 将某个元素移动到某个元素后面    l.Remove(l.Front().Next())                            // 移除某个元素    fmt.Printf("%T %+[1]v %p\n", l, &l)    for i := l.Front(); i != nil; i = i.Next() {        fmt.Printf("%T %[1]v\n", i)        fmt.Println(i.Next())    }}
示例0

list结构体

示例:*list.List &{root:{next:0xc000076510 prev:0xc000076510 list: Value:} len:0} 0xc00000a028,这是一个空list的元数据,其中记录了next、prev、len等数据。

下面是一个示例

package mainimport (    "container/list"    "fmt")func main() {    s := make([]int, 5)    l := list.New()    fmt.Printf("%T %+[1]v %p\n", l, &l)    l.PushBack(2)    l.PushFront("first")    l.PushBack("你好吗")    e := l.Front().Next()    l.InsertAfter("c", e)    l.InsertBefore(3.14, e)    l.InsertBefore(s, e)    l.PushBack("last")    fmt.Printf("%T %+[1]v %p\n", l, &l)    for i := l.Front(); i != nil; i = i.Next() {        fmt.Printf("%T %[1]v\n", i)    }}
示例1

我在执行了上面的代码后,返回是这样的:

*list.List &{root:{next:0xc000076510 prev:0xc000076510 list: Value:} len:0} 0xc00000a028*list.List &{root:{next:0xc0000765a0 prev:0xc000076690 list: Value:} len:7} 0xc00000a028*list.Element &{0xc000076630 0xc000076510 0xc000076510 first}*list.Element &{0xc000076660 0xc0000765a0 0xc000076510 3.14}*list.Element &{0xc000076570 0xc000076630 0xc000076510 [0 0 0 0 0]}*list.Element &{0xc000076600 0xc000076660 0xc000076510 2}*list.Element &{0xc0000765d0 0xc000076570 0xc000076510 99}*list.Element &{0xc000076690 0xc000076600 0xc000076510 你好吗}*list.Element &{0xc000076510 0xc0000765d0 0xc000076510 last}

从返回中,可以看到头部元素的prev和尾部元素的next都指向了0xc000076510 地址,通过这个地址完成了list的闭环。下面我使用图来表达,地址简写为后三位表达:

疑问:

1、上面示例中,在遍历元素的时候,发现每次都会打印0xc000076510这个指针,这是个什么指针?为什么每个元素都包含?

答:因为在使用list.New()来创建一个列表的时候,是创建了一个 list.List实例,而该实例的所有元素都是通过该实例的指针进行访问和操作的。

具体来说,每个元素都是 list.Element类型的结构体,其中包含了 Value字段表示节点的值,以及 Next()Prev()方法表示指向下一个节点和上一个节点的指针。第三个指针就是表达指向该元素所在的 list.List实例的指针。所以每次打印都会相同。

关键词: