Go标准库:container/list
原创 孟斯特 孟斯特 2024-07-03 16:03 北京 听全文在Go语言的标准库中,container/list
包提供了一个双向链表的实现,这对于需要频繁插入和删除操作的场景非常有用。双向链表是一种线性数据结构,它由一系列节点组成,每个节点包含数据和两个指针,分别指向前一个节点和后一个节点。下面我们将详细介绍如何使用container/list
包,以及它的内部实现和常见操作。
导入包
首先,我们需要导入container/list
包:
import "container/list"
初始化链表
我们可以通过调用list.New()
函数或者直接声明一个list.List
类型的变量来初始化一个链表:
// 方法一:使用list.New()函数
l := list.New()
// 方法二:直接声明一个list.List变量
var l list.List
基本操作
添加元素
container/list
包提供了多种方法来向链表中添加元素:
-
•
PushFront(v interface{}) *Element
:在链表的头部插入一个元素,返回该元素的指针。 -
•
PushBack(v interface{}) *Element
:在链表的尾部插入一个元素,返回该元素的指针。 -
•
InsertBefore(v interface{}, mark *Element) *Element
:在指定元素之前插入一个新元素。 -
•
InsertAfter(v interface{}, mark *Element) *Element
:在指定元素之后插入一个新元素。
l := list.New()
l.PushBack("Go")
l.PushFront(42)
e := l.PushBack(3.14)
l.InsertBefore("before", e)
l.InsertAfter("after", e)
删除元素
可以使用Remove
方法删除链表中的元素,Remove
方法接受一个指向链表元素的指针,删除该元素并返回其值:
l := list.New()
e := l.PushBack("to be removed")
l.Remove(e)
遍历链表
可以使用Front()
和Back()
方法获取链表的第一个和最后一个元素,然后通过元素的Next()
和Prev()
方法进行遍历:
// 从前向后遍历
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
// 从后向前遍历
for e := l.Back(); e != nil; e = e.Prev() {
fmt.Println(e.Value)
}
链表的特性
-
• 双向链表:每个节点有两个指针,分别指向前一个节点和后一个节点。
-
• O(1)时间复杂度的插入和删除:链表的插入和删除操作都只需要调整指针,因此效率很高。
-
• 遍历效率较低:由于链表节点不连续存储,无法利用CPU缓存,遍历效率相对于数组较低。
常见应用场景
-
1. 需要频繁插入和删除操作的场景:由于链表插入和删除操作的时间复杂度为O(1),在需要频繁进行这些操作时,链表表现优异。
-
2. 实现LRU缓存:链表和哈希表的结合可以高效实现LRU(最近最少使用)缓存。
-
3. 队列和双端队列:链表可以方便地实现FIFO队列和双端队列。
示例:实现一个简单的LRU缓存
下面是一个使用container/list
和map
实现的简单LRU缓存的例子:
package main
import(
"container/list"
"fmt"
)
typeLRUCachestruct{
capacity int
list *list.List
cache map[int]*list.Element
}
type entry struct{
key int
value int
}
func NewLRUCache(capacity int)*LRUCache{
return&LRUCache{
capacity: capacity,
list: list.New(),
cache:make(map[int]*list.Element),
}
}
func (c *LRUCache)Get(key int)(int,bool){
if e, ok = c.cache[key]; ok {
c.list.MoveToFront(e)
return e.Value.(*entry).value,true
}
return-1,false
}
func (c *LRUCache)Put(key, value int){
if e, ok = c.cache[key]; ok {
c.list.MoveToFront(e)
e.Value.(*entry).value = value
}else{
if c.list.Len()== c.capacity {
back := c.list.Back()
c.list.Remove(back)
delete(c.cache, back.Value.(*entry).key)
}
e :=&entry{key, value}
listElement := c.list.PushFront(e)
c.cache[key]= listElement
}
}
func main(){
cache :=NewLRUCache(2)
cache.Put(1,1)
cache.Put(2,2)
fmt.Println(cache.Get(1))// 返回1
cache.Put(3,3)
fmt.Println(cache.Get(2))// 返回-1 (未找到)
cache.Put(4,4)
fmt.Println(cache.Get(1))// 返回-1 (未找到)
fmt.Println(cache.Get(3))// 返回3
fmt.Println(cache.Get(4))// 返回4
}
孟斯特
个人分享
258篇原创内容
公众号
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)[1]进行许可,使用时请注明出处。
Author: mengbin[2]
blog: mengbin[3]
Github: mengbin92[4]
cnblogs: 恋水无意[5]
腾讯云开发者社区:孟斯特[6]
引用链接
[1]
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0): https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh[2]
mengbin: [email protected][3]
mengbin: https://mengbin.top[4]
mengbin92: https://mengbin92.github.io/[5]
恋水无意: https://www.cnblogs.com/lianshuiwuyi/[6]
孟斯特: https://cloud.tencent.com/developer/user/6649301
Golang132 Golang · 目录 上一篇PKCS#12 个人观点,仅供参考 阅读 18 喜欢此内容的人还喜欢 单元测试 我关注的号 孟斯特 不看的原因
- 内容低质
- 不看此公众号内容
- 内容低质
- 不看此公众号内容
- 内容低质
- 不看此公众号内容
人划线
标签:元素,container,int,cache,list,链表,Go From: https://www.cnblogs.com/cheyunhua/p/18282289