源码地址https://github.com/golang/go/tree/master/src/container

list

链表就是一个有 prev 和 next 指针的数组了

  1. type Element struct {
  2. next, prev *Element // 上一个和下一个元素
  3. list *List // 元素所在的链表
  4. Value interface{} // 元素
  5. }
  6. type List struct {
  7. root Element // 链表的根节点
  8. len int // 链表的长度
  9. }


常用方法

  1. type Element
  2. func (e *Element) Next() *Element
  3. func (e *Element) Prev() *Element
  4. type List
  5. func New() *List
  6. func (l *List) Back() *Element // 最后一个元素
  7. func (l *List) Front() *Element // 第一个元素
  8. func (l *List) Init() *List // 链表初始化
  9. func (l *List) InsertAfter(v interface{}, mark *Element) *Element // 在某个元素后插入
  10. func (l *List) InsertBefore(v interface{}, mark *Element) *Element // 在某个元素前插入
  11. func (l *List) Len() int // 在链表长度
  12. func (l *List) MoveAfter(e, mark *Element) // 把 e 元素移动到 mark 之后
  13. func (l *List) MoveBefore(e, mark *Element) // 把 e 元素移动到 mark 之前
  14. func (l *List) MoveToBack(e *Element) // 把 e 元素移动到队列最后
  15. func (l *List) MoveToFront(e *Element) // 把 e 元素移动到队列最头部
  16. func (l *List) PushBack(v interface{}) *Element // 在队列最后插入元素
  17. func (l *List) PushBackList(other *List) // 在队列最后插入接上新队列
  18. func (l *List) PushFront(v interface{}) *Element // 在队列头部插入元素
  19. func (l *List) PushFrontList(other *List) // 在队列头部插入接上新队列
  20. func (l *List) Remove(e *Element) interface{} // 删除某个元素

eg:

  1. package main
  2. import (
  3. "container/list"
  4. "fmt"
  5. )
  6. func main() {
  7. l := list.New()
  8. for i:=1;i<5;i++{
  9. l.PushBack(i)
  10. }
  11. fmt.Println(l.Front().Value)//输出首部元素的值
  12. fmt.Println(l.Back().Value)//输出尾部元素的值
  13. // 遍历链表
  14. for e :=l.Front();e!=nil;e =e.Next(){
  15. fmt.Print(e.Value)
  16. }
  17. fmt.Println("")
  18. l.InsertBefore(0, l.Front()) //首部元素之前插入0
  19. l.MoveToBack(l.Front()) //将0元素移动到末尾
  20. for e := l.Front(); e != nil; e = e.Next() {
  21. fmt.Print(e.Value)
  22. }
  23. fmt.Println("")
  24. l2 := list.New()
  25. l2.PushBackList(l) //将l中元素放在l2的末尾
  26. l2.MoveToFront(l2.Back()) // 将末尾元素移到首部
  27. for e := l2.Front(); e != nil; e = e.Next() {
  28. fmt.Print(e.Value)
  29. }
  30. fmt.Println("")
  31. l.Init() //清空l
  32. fmt.Println(l.Len()) //0
  33. }

程序执行结果

  1. 1
  2. 4
  3. 1234
  4. 12340
  5. 01234
  6. 0

ring

环的尾部就是头部,所以每个元素实际上就可以代表自身的这个环。 它不需要像 list 一样保持 list 和 element 两个结构,只需要保持一个结构就行

  1. type Ring struct {
  2. next, prev *Ring
  3. Value interface{}
  4. }

常用方法

  1. func New(n int) *Ring // 初始化环
  2. func (r *Ring) Do(f func(interface{})) // 循环环进行操作
  3. func (r *Ring) Len() int // 环长度
  4. func (r *Ring) Link(s *Ring) *Ring // 连接两个环
  5. func (r *Ring) Move(n int) *Ring // 指针从当前元素开始向后移动或者向前(n 可以为负数)
  6. func (r *Ring) Next() *Ring // 当前元素的下个元素
  7. func (r *Ring) Prev() *Ring // 当前元素的上个元素
  8. func (r *Ring) Unlink(n int) *Ring // 从当前元素开始,删除 n 个元素

heap

  1. type Interface interface {
  2. sort.Interface
  3. Push(x interface{}) // add x as element Len()
  4. Pop() interface{} // remove and return element Len() - 1.
  5. }
  1. package sort
  2. // A type, typically a collection, that satisfies sort.Interface can be
  3. // sorted by the routines in this package. The methods require that the
  4. // elements of the collection be enumerated by an integer index.
  5. type Interface interface {
  6. // Len is the number of elements in the collection.
  7. Len() int
  8. // Less reports whether the element with
  9. // index i should sort before the element with index j.
  10. Less(i, j int) bool
  11. // Swap swaps the elements with indexes i and j.
  12. Swap(i, j int)
  13. }

堆结构继承自 sort.Interface, 回顾下 sort.Interface,它需要实现三个方法

  • Len() int
  • Less(i, j int) bool
  • Swap(i, j int)

加上堆接口定义的两个方法

  • Push(x interface{})
  • Pop() interface{}

Push

push方法,其官方注释要求实现的功能写的很简单,事实上也确实很简单。
将x添加在数组最后即可,所以实现代码如下:

  1. func (h *IntHeap) Push(x interface{}) {
  2. // Push and Pop use pointer receivers because they modify the slice's length,
  3. // not just its contents.
  4. *h = append(*h, x.(int))
  5. }

你可能会疑惑,如果只是实现这样得Push函数,并没有保证堆的性质啊,你只是把这个数放到了数组最后。实际上这是官方为了避免我们写太多代码而做的设计,我们在push时实际上是调用heap.Push(h, 3) ,这是在heap.go中的一个函数,其具体实现为:

  1. func Push(h Interface, x interface{}) {
  2. h.Push(x)
  3. up(h, h.Len()-1)
  4. }
  5. func up(h Interface, j int) {
  6. for {
  7. i := (j - 1) / 2 // parent
  8. if i == j || !h.Less(j, i) {
  9. break
  10. }
  11. h.Swap(i, j)
  12. j = i
  13. }
  14. }

Pop

  1. func Pop(h Interface) interface{} {
  2. n := h.Len() - 1
  3. h.Swap(0, n)
  4. down(h, 0, n)
  5. return h.Pop()
  6. }
  7. func down(h Interface, i0, n int) bool {
  8. i := i0
  9. for {
  10. j1 := 2*i + 1
  11. if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
  12. break
  13. }
  14. j := j1 // left child
  15. if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
  16. j = j2 // = 2*i + 2 // right child
  17. }
  18. if !h.Less(j, i) {
  19. break
  20. }
  21. h.Swap(i, j)
  22. i = j
  23. }
  24. return i > i0
  25. }

eg:

  1. package main
  2. import (
  3. "container/heap"
  4. "fmt"
  5. )
  6. type myHeap []int
  7. func(h myHeap)Len()int{
  8. return len(h)
  9. }
  10. func(h myHeap)Swap(i,j int){
  11. h[i],h[j] = h[j],h[i]
  12. }
  13. func(h myHeap)Less(i,j int)bool{
  14. return h[i]>h[j]
  15. }
  16. func(h *myHeap)Push(v interface{}){
  17. *h = append(*h,v.(int))
  18. }
  19. func(h *myHeap)Pop()(v interface{}){
  20. *h,v =(*h)[:len(*h)-1],(*h)[len(*h)-1]
  21. return
  22. }
  23. // 按层来遍历和打印堆数据,第一行只有一个元素,即堆顶元素
  24. func (h myHeap) printHeap() {
  25. n := 1
  26. levelCount := 1
  27. for n <= h.Len() {
  28. fmt.Println(h[n-1 : n-1+levelCount])
  29. n += levelCount
  30. levelCount *= 2
  31. }
  32. }
  33. // 大顶堆小堆的结果主要swap
  34. func main() {
  35. list :=[7]int{13,12,45,24,11,9,20}
  36. hq := make(myHeap,0)
  37. for i :=range list{
  38. hq.Push(list[i])
  39. }
  40. heap.Init(&hq)
  41. hq.printHeap()
  42. }

打印结果

  1. [45]
  2. [24 20]
  3. [12 11 9 13]

参考

https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter03/03.3.html
https://blog.csdn.net/weixin_40631132/article/details/105208272