Go语言列表(list)的创建和使用
列表(list)是一种非连续的存储容器,由多个节点组成,节点通过一些变量记录彼此之间的关系,列表有多种实现方法,如单链表、双链表等。
在 Go 语言中,列表使用 container/list 包来实现,内部的实现原理是双链表,列表能够高效地进行任意位置的元素插入和删除操作。
1) 通过 container/list 包的 New() 函数初始化 list,语法格式如下:
2) 通过 var 关键字声明初始化 list,语法格式如下:
这两种方法都会返回一个 *list.Element 结构,如果需要删除插入的元素,则只能通过 *list.Element 配合 Remove() 方法进行删除,这种方法可以让删除更加高效,同时也是双链表的特性之一。
例如,给 list 列表添加元素的代码如下:
列表插入元素的方法如表 1 所示。
例如,列表操作元素的代码如下:
列表元素的操作过程如下表所示。
在 Go 语言中,列表使用 container/list 包来实现,内部的实现原理是双链表,列表能够高效地进行任意位置的元素插入和删除操作。
初始化列表
list 的初始化有两种方法,分别是使用 New() 函数和 var 关键字声明。两种方法的初始化效果是相同的。1) 通过 container/list 包的 New() 函数初始化 list,语法格式如下:
变量名 := list.New()
2) 通过 var 关键字声明初始化 list,语法格式如下:
var 变量名 list.List列表与切片和 map 不同的是,列表并没有具体元素类型的限制,因此,列表的元素可以是任意类型,这既带来了便利,也引来一些问题,例如,给列表中放入了一个 interface{} 类型的值,取出值后,如果要将 interface{} 转换为其他类型,将会发生宕机。
在列表中插入元素
双链表支持从队列前方或后方插入元素,对应的方法分别是 PushFront() 和 PushBack()。这两种方法都会返回一个 *list.Element 结构,如果需要删除插入的元素,则只能通过 *list.Element 配合 Remove() 方法进行删除,这种方法可以让删除更加高效,同时也是双链表的特性之一。
例如,给 list 列表添加元素的代码如下:
l := list.New() l.PushBack("fist") l.PushFront(67)在以上代码中:
- 第 1 行,创建一个列表实例。
- 第 2 行,将 fist 字符串插入到列表的尾部,此时列表是空的,插入后只有一个元素。
- 第 3 行,将数值 67 放入列表,此时,列表中已经存在 fist 元素,67 这个元素将被放在 fist 的前面。
列表插入元素的方法如表 1 所示。
方 法 | 功 能 |
---|---|
InsertAfter(v interface {}, mark * Element) * Element | 在 mark 点之后插入元素,mark 点由其他插入函数提供 |
InsertBefore(v interface {}, mark * Element) ^Element | 在 mark 点之前插入元素,mark 点由其他插入函数提供 |
PushBackList(other *List) | 添加 other 列表元素到尾部 |
PushFrontList(other *List) | 添加 other 列表元素到头部 |
从列表中删除元素
列表插入函数的返回值会提供一个 *list.Element 结构,这个结构记录着列表元素的值及与其他节点之间的关系等信息,从列表中删除元素时,需要用到这个结构进行快速删除。例如,列表操作元素的代码如下:
package main import "container/list" func main() { l := list.New() //尾部添加 l.PushBack("canon") //头部添加 l.PushFront(67) //尾部添加后保存元素句柄 element := l.PushBack("fist") //在fist之后添加high l.InsertAfter("high", element) //在fist之前添加noon l.InsertBefore("noon", element) //使用 l.Remove(element) }在以上代码中:
- 第 4 行,创建列表实例。
- 第 6 行,将字符串 canon 插入到列表的尾部。
- 第 8 行,将数值 67 添加到列表的头部。
- 第 10 行,将字符串 fist 插入到列表的尾部,并将这个元素的内部结构保存到 element 变量中。
- 第 12 行,使用 element 变量,在 element 后面插入 high 字符串。
- 第 14 行,使用 element 变量,在 element 前面插入 noon 字符串。
- 第 16 行,移除 element 变量对应的元素。
列表元素的操作过程如下表所示。
操作内容 | 列表元素 |
---|---|
l.PushBack("canon") | canon |
l.PushFront(67) | 67, canon |
element := l.PushBack("fist") |
67, canon, fist |
l.InsertAfter("high", element) | 67, canon, fist, high |
l.InsertBefore("noon", element) | 67, canon, noon, fist, high |
l.Remove(element) | 67, canon, noon, high |
列表的遍历
遍历双链表需要配合 Front() 函数获取头元素,遍历时只要元素不为空就可以继续进行,每次遍历都会调用元素的 Next() 函数,例如:l := list.New() //尾部添加 l.PushBack("canon") //头部添加 l.PushFront(67) for i := l.Front(); i != nil; i = i.Next() { fmt.Println(i.Value) }运行结果如下:
67
canon
- 第 1 行,创建一个列表实例。
- 第 3 行,将 canon 放入列表尾部。
- 第 5 行,在队列头部放入 67。
- 第 6 行,使用 for 语句进行遍历,其中 i:=l.Front() 表示初始赋值,只会在一开始执行一次,每次循环会进行一次 i != nil 语句判断,如果返回 false,表示退出循环,反之则会执行 i = i.Next()。
- 第 7 行,使用遍历返回的 *list.Element 的 Value 成员取得放入列表时的原值。