golang 集合包阅读container包

1、list包详解,list实现了个双端队列

//这是一个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 *List

    // The value stored with this element.
    //存储的值,使用interface来代替泛型
    Value interface{}
}
//返回list的下一个元素
func (e *Element) Next() *Element{}
//返回list的上一个元素
func (e *Element) Prev() *Element{}
//list结构
type List struct {
//根元素,就是头节点,头节点的next,prev指向当前的元素
    root Element // sentinel list element, only &root, root.prev, and root.next are used
    len  int     // current list length excluding (this) sentinel element
}
list中的方法
// insert inserts e after at, increments l.len, and returns e.
//插入e元素再at元素之后,就是指定插入
func (l *List) insert(e, at *Element) *Element{}

// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
//插入一个值到at元素中
func (l *List) insertValue(v interface{}, at *Element) *Element{}

// remove removes e from its list, decrements l.len, and returns e.
//删除list中的e元素
func (l *List) remove(e *Element) *Element{}
// PushFront inserts a new element e with value v at the front of list l and returns e.
//插入一个元素在root的头
func (l *List) PushFront(v interface{}) *Element{}
 PushBack inserts a new element e with value v at the back of list l and returns e.
//插入一个元素在list的末尾
func (l *List) PushBack(v interface{}) *Element{}

// InsertBefore inserts a new element e with value v immediately before mark and returns e.
// If mark is not an element of l, the list is not modified.
//插入一个新元素的值为v在mark之前并返回这个元素,若这个元素不是当前的list
func (l *List) InsertBefore(v interface{}, mark *Element) *Element{}
// InsertAfter inserts a new element e with value v immediately after mark and returns e.
// If mark is not an element of l, the list is not modified.
//插入一个元素,值为v,在mark的后面,并返回这个元素,如果mark不是当前list的元素,则list时不能修改的
func (l *List) InsertAfter(v interface{}, mark *Element) *Element{}

使用用例

func Example() {
    // Create a new list and put some numbers in it.
    l := list.New()
    e4 := l.PushBack(4) //插入到末尾
    e1 := l.PushFront(1)//插入到头元素
    l.InsertBefore(3, e4) //插入到e4元素之前
    l.InsertAfter(2, e1)//插入e1元素之后

    // Iterate through list and print its contents.
    for e := l.Front(); e != nil; e = e.Next() {
        fmt.Println(e.Value)
    }

    // Output:
    // 1
    // 2
    // 3
    // 4
}

2、Ring包实现了环形链表的操作

// A Ring is an element of a circular list, or ring.
// Rings do not have a beginning or end; a pointer to any ring element
// serves as reference to the entire ring. Empty rings are represented
// as nil Ring pointers. The zero value for a Ring is a one-element
// ring with a nil Value.
//
//环形链表的数据结构时一个环形list的元素或者圆环,
//一个圆环链表是一个圆形list或者圆的元素,没有开始和结束,
type Ring struct {
    next, prev *Ring
    Value      interface{} // for use by client; untouched by this library
}

圆环链表的一些操作方法

// Next returns the next ring element. r must not be empty.
//返回圆环的下一个元素,圆环必须不为空
func (r *Ring) Next() *Ring{}
// Prev returns the previous ring element. r must not be empty.
//返回这个圆环的上一个元素
func (r *Ring) Prev() *Ring{}
//当n<0时,反向移动元素,n>0时,正向移动元素
func (r *Ring) Move(n int) *Ring{}
//New creates a ring of n elements.
//新创建n个集合的圆环
func New(n int) *Ring{}
//统计 圆环长度
func (r *Ring) Len() int{}
//Link连接r和s,并返回r原本的后继元素r.Next()。r不能为空。如果r和s指向同一个环形链表,则会删除掉r和s之间的元素,删掉的元素构成一个子链表,返回指向该子链表的指针(r的原后继元素);如果没有删除元素,则仍然返回r的原后继元素,而不是nil。如果r和s指向不同的链表,将创建一个单独的链表,将s指向的链表插入r后面,返回s原最后一个元素后面的元素(即r的原后继元素)。
func (r *Ring) Link(s *Ring) *Ring{}
//删除链表中n % r.Len()个元素,从r.Next()开始删除。如果n % r.Len() == 0,不修改r。返回删除的元素构成的链表,r不能为空。
func (r *Ring) Unlink(n int) *Ring {}
//对链表中任意元素执行f操作,如果f改变了r,则该操作造成的后果是不可预期的。
func (r *Ring) Do(f func(interface{}))

3、heap堆结构

//heap结构只写了一个接口
type Interface interface {
    sort.Interface //接口的组合(接口继承),继承sort(排序接口),子类就可调用排序的方法
    Push(x interface{}) // add x as element Len()
    Pop() interface{}   // remove and return element Len() - 1.
}
//要实现这个接口,必须实现所有的方法,包括继承了的接口
实现这五个方法,这五个方法可能实现个不一样,真真的需求完全交给用户
func down(i,n int) {
    //构建最小堆,父小于两子节点值
    for {   

        j1 := 2*i + 1
        if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
            break
        }

        //找出两个节点中最小的(less: a<b)
        j := j1 // left child       
        if j2 := j1 + 1; j2 < n && !Less(j1, j2) {
            j = j2 // = 2*i + 2  // right child
        }

        //然后与父节点i比较,如果父节点小于这个子节点最小值,则break,否则swap
        if !Less(j, i) {
            break
        }
        Swap(i, j)
        i = j   
    }
}


//由子节点至父节点依次重建堆
func up(j int)  {

    for {
        i := (j - 1) / 2 // parent      

        if i == j || !Less(j, i) { 
            //less(子,父) !Less(9,5) == true 
            //父节点小于子节点,符合最小堆条件,break
            break
        }
        //子节点比父节点小,互换
        Swap(i, j)
        j = i
    }
}

func Push(x interface{}){
    heap = append(heap, x.(int))
    up(len(heap)-1)
    return 
}

func Pop() interface{} {
    n := len(heap) - 1
    Swap(0, n)
    down(0, n)

    old :=heap
    n = len(old)
    x := old[n-1]
    heap = old[0 : n-1]
    return x
}

func Remove(i int) interface{} {
    n := len(heap) - 1
    if n != i {
        Swap(i, n)
        down(i, n)
        up(i)
    }
    return Pop()
}

func Less(a,b int)bool{
    return heap[a] < heap[b]


func Swap(a,b int){
    heap[a],heap[b] = heap[b],heap[a]
}
//源码中实现了一个堆排序需要的堆方法,就是上面的几个方法,下面这个就是一个堆排序的使用
func HeapSort(){
    //升序 Less(heap[a] > heap[b])    //最大堆
    //降序 Less(heap[a] < heap[b])    //最小堆
    for i := len(heap)-1 ;i > 0;i--{    
        //移除顶部元素到数组末尾,然后剩下的重建堆,依次循环
        Swap(0, i)
        down(0, i)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值