golang 在container包下提供了list(双链表)、heap(堆)、ring(环)等容器结构 ![[Pasted image 20231225085517.png]] # 一、list golang 中实现的list为双向链表。双向链表一般用于经常堆头部和尾部进行增删的场景,同时它不需要在一开始初始化它的容量,它的容量随着使用动态变化(扩大or缩小)。 核心数据结构(Element、List): ```golang // 链表的一个元素 type Element struct { next, prev *Element // 前后指针 list *List // 所属链表 Value any // 值 } ``` ```golang // 链表 type List struct { root Element // 哨兵元素 len int // 链表元素个数 } ``` ![[Pasted image 20231225170420.png]] ## 1.初始化 ```golang package main import ( "container/list" "fmt" ) func main() // 使用list.New()直接初始化 l1 := list.New() l1.PushFront(1) fmt.Println(l1.Front().Value) // 1 // 使用list.List{}延迟初始化 l2 := list.List{} l2.PushFront(2) fmt.Println(l2.Front().Value) // 2 } ``` ## 2.常用API + PushFront 链表头部添加元素 + PushBack 尾部添加元素 + PushFrontList 链表头部插入链表 + PushBackList 尾部插入链表 + Front 获取头部元素 + Back 获取尾元素 + Len 获取长度 + InsertBefore 某个元素前插入 + InsertAfter 某个元素后插入 + MoveBefore 移动元素到某个元素前面 + MoveAfter 移动元素到某个元素后面 + MoveToFront 移动元素到头部 + MoveToBack 移动元素到尾部 # 二、heap 堆是一颗完全二叉树,按照比较规则不同,分为最大堆和最小堆。以最小堆为例,父节点总是比子节点小。 堆的下标公式: parent(i)=floor((i-1)/2) 向下取整 left(i)=2i+1 right(i)=2i+2 golang 提供了最小堆算法,其中包含5个接口需要开发者自行实现(**作为官方包,Golang 希望提供给大家一种简单的接入方式,官方提供好算法的内核,大家接入就 ok。采用的是定义一个接口,开发者来实现的方式**) ```golang type Interface interface { sort.Interface Push(x any) // 入堆 Pop() any // 出堆 } type Interface interface { Len() int //堆大小 Less(i, j int) bool //比较 Swap(i, j int) //交换 } ``` ## 例一:最小堆 ```golang package mycontainer type IntHeap []int // Push IntHeap全局共享切只有一个,所以需要对类型本身进行操作,所以使用指针 func (h *IntHeap) Push(x any) { //append需要传入切片,切片是引用传递所以需要*h, *h = append(*h, x.(int)) } // Pop // // @Description: 从数组移除一个元素 // @receiver h // @return any func (h *IntHeap) Pop() any { old := *h n := len(old) x := old[n-1] *h = old[0 : n-1] return x } // Len // // @Description: 计算元素大小 // @receiver h // @return int func (h IntHeap) Len() int { return len(h) } // Less // // @Description: 比较大小 // @receiver h // @param i // @param j // @return bool func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] } // Swap // // @Description: 交换i,j下标元素 // @receiver h // @param i // @param j func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } // TestIntHeap // // @Description: 测试自定义堆 // @param t func TestIntHeap(t *testing.T) { //因为pop和push方法需要传入指针 h := &myc.IntHeap{7, 9, 10} print(h) //堆初始化,用于构建二叉树 heap.Init(h) //添加元素 heap.Push(h, 3) fmt.Printf("minimum: %d\n", (*h)[0]) for h.Len() > 0 { fmt.Printf("%d ", heap.Pop(h)) } } ``` ## 例二:优先队列 ```golang type Item struct { value string priority int index int } type PriorityQueue []*Item func (p *PriorityQueue) Push(x any) { n := len(*p) item := x.(*Item) item.index = n *p = append(*p, item) } func (p *PriorityQueue) Pop() any { old := *p n := len(old) item := old[n-1] item.index = -1 *p = old[0 : n-1] return item } func (p PriorityQueue) Len() int { return len(p) } func (p PriorityQueue) Less(i, j int) bool { return p[i].priority > p[j].priority } func (p PriorityQueue) Swap(i, j int) { p[i], p[j] = p[j], p[i] p[i].index = i p[j].index = j } // 更新元素优先级 func (p *PriorityQueue) update(item *Item, value string, priority int) { item.value = value item.priority = priority //二叉堆重排序 heap.Fix(p, item.index) } ``` # 三、ring