
题图:pixabay
container 包
这个包讲了3个数据结构,堆(heap)、链表(list)、环(ring)
heap(堆)
//要实现这个接口需要写5个方法type Interface interface {继承 sort.Interface,也就是下面的那个sort.InterfacePush(x interface{}) add x as element Len()Pop() interface{} remove and return element Len() - 1.}//sort.Interfacetype Interface interface {Len is the number of elements in the collection.Len() intLess reports whether the element withindex i should sort before the element with index j.Less(i, j int) boolSwap swaps the elements with indexes i and j.Swap(i, j int)}
这里的堆使用的数据结构是一个最小二叉树,任意父节点比左右子树节点都要小。也就是最小二叉堆。
核心方法是这两个:维护着最小二叉堆
func up(h Interface, j int) {for {一直找j的父节点i := (j - 1) 2 parentif i == j || !h.Less(j, i) {如果自己就是或者小于父节点就退出break}/否则交换h.Swap(i, j)j = i}}func down(h Interface, i0, n int) bool {//i0代表需要down的元素在数组中的索引//n代表长度i := i0for {j1 := 2*i + 1if j1 >= n || j1 < 0 { // j1 < 0 after int overflow//越界跳出break}//左子节点索引j := j1 // left childif j2 := j1 + 1; j2 < n && h.Less(j2, j1) {//j2 右子节点索引j = j2}//父节点 > 右子节点,则交换位置if !h.Less(j, i) {break}h.Swap(i, j)i = j}return i > i0}
下面讲讲添加元素和删除元素怎么保证最小二叉堆
/ Push pushes the element x onto the heap.// The complexity is O(log n) where n = h.Len().func Push(h Interface, x interface{}) {//在最后头添加一个元素h.Push(x)//然后上升up(h, h.Len()-1)}
// Remove removes and returns the element at index i from the heap.// The complexity is O(log n) where n = h.Len().func Remove(h Interface, i int) interface{} {n := h.Len() - 1if n != i {//把要删除的跟最后一个交换h.Swap(i, n)//然后下沉或上升到合适的位置if !down(h, i, n) {up(h, i)}}//把最后一个干掉return h.Pop()}// Pop removes and returns the minimum element (according to Less) from the heap.// The complexity is O(log n) where n = h.Len().// Pop is equivalent to Remove(h, 0).//删除最上面的元素func Pop(h Interface) interface{} {n := h.Len() - 1//把根节点跟最后一个交换h.Swap(0, n)//然后下沉到合适的位置down(h, 0, n)//把最后一个干掉return h.Pop()}
heap 可以用来构建优先队列 xeample_pq_test.go
list(链表)
//元素type Element struct {// Next and previous pointers in the doubly-linked list of elements.// To simplify the implementation, internally a list l is implemented// as a ring, such that &l.root is both the next element of the last// list element (l.Back()) and the previous element of the first list// element (l.Front()).//前指针、后指针next, prev *Element// The list to which this element belongs.list *List// The value stored with this element.Value interface{}}// List represents a doubly linked list.// The zero value for List is an empty list ready to use.//双向链表//双向是由Element里的next/prev决定的。如果只有一个就是单链表type List struct {root Element // sentinel list element, only &root, root.prev, and root.next are usedlen int // current list length excluding (this) sentinel element}
开始
//初始化一个双向链表,前后指针都指向自己// Init initializes or clears list l.func (l *List) Init() *List {l.root.next = &l.rootl.root.prev = &l.rootl.len = 0return l}// New returns an initialized list.func New() *List { return new(List).Init() }
几个关键函数
//在at元素的后面插入一个e元素// insert inserts e after at, increments l.len, and returns e.func (l *List) insert(e, at *Element) *Element {//n := at.next//修改指针指向,先修改要插入的那个元素的前一个元素后指针,指向e元素at.next = e//修改要插入的元素的前指针e.prev = at//把e元素的后指针指向原来at元素的后面一个元素e.next = n//原本at元素的前指针就指向e元素了n.prev = ee.list = ll.len++//返回要插入的元素return e}//移出一个元素// remove removes e from its list, decrements l.len, and returns e.func (l *List) remove(e *Element) *Element {//把e前一个元素的后指针指向e的下一个元素e.prev.next = e.next//再把e后一个元素的前指针指向e的前一个元素e.next.prev = e.prev//销毁指针值e.next = nil // avoid memory leakse.prev = nil // avoid memory leaks//销毁data域e.list = nil// - lenl.len--return e}// move moves e to next to at and returns e.//移动元素//其实就是把插入跟移出结合了//把e元素挪到at元素后面func (l *List) move(e, at *Element) *Element {if e == at {return e}e.prev.next = e.nexte.next.prev = e.prevn := at.nextat.next = ee.prev = ate.next = nn.prev = ereturn e}
其他还有一些方法可以自己看源码
ring(环)
环也是一个链表,是一条收尾相连的链表。
type Ring struct {next, prev *RingValue interface{} // for use by client; untouched by this library}
新建一个环
// New creates a ring of n elements.func New(n int) *Ring {if n <= 0 {return nil}r := new(Ring)p := rfor i := 1; i < n; i++ {//多个元素,首尾相连起来p.next = &Ring{prev: p}p = p.next}//再把最后一个后指针指向第一个元素p.next = r//把第一个元素的前指针指向最后一个元素r.prev = preturn r}
其他的没啥讲的。
//由有一个do方法遍历huan// Do calls function f on each element of the ring, in forward order.// The behavior of Do is undefined if f changes *r.func (r *Ring) Do(f func(interface{})) {if r != nil {f(r.Value)for p := r.Next(); p != r; p = p.next {f(p.Value)}}}
文章转载自花一个无所,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




