go语言container/heap 源码解读与应用阅读笔记

golang container/heap源码阅读笔记

1. 源码解析

type Interface interface {
   
	sort.Interface
    Push(x interface{
   }) // add x as element Len()  将x作为第len()个元素加入堆中
	Pop() interface{
   }   // remove and return element Len() - 1. 
}

首先定义heap的接口,其中 sort.Interface包括一下三个接口,任何类型,只要实现了这五个接口,就是一个heap

Interface interface {
   
    // Len is the number of elements in the collection. 集合内的元素个数
    Len() int
    // Less reports whether the element with
    // index i should sort before the element with index j.
    // 返会索引为i的元素是否应该在j的前面
    Less(i, j int) bool
    // Swap swaps the elements with indexes i and j.
    Swap(i, j int)
}

在这里插入图片描述

堆的逻辑结构是满二叉树,堆的常用的存储结构有顺序存储、链表存储,go的官方源码采用的是顺序结构。

以小根堆为例说明

down()函数是从上到下调整的过程,就是从节点i0开始,将其与子节点中较小的节点交换,直到i最后的位置为叶节点或者以i为父节点的子树满足小根堆的要求。

如果发生了交换,i就比i0大,否则 i等于i0 返回值 i>i0表示是否发生的交换

func down(h Interface, i0, n int) bool {
   
	i := i0
	for {
   
		j1 := 2*i + 1
		if j1 >= n || j1 < 0 {
    // j1 < 0 after int overflow
			break
		}
        // 如果j1大于n,说明索引i没有孩子节点,说明它本身就是孩子节点,此时已经
		j := j1 // left child
		if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
   
            // 判断右孩子节点是否存在,且 如果小于j1,就将j2赋值给j
			j = j2 // = 2*i + 2  // right child
		}
        // 此时得到的j为i的两个孩子节点较小的索引
		if !h.Less(j, i) {
   
            // 判断 孩子节点与父节点是否需要交换,如果不需要,说明已经满足堆的要求(小根或者大根)
			break
		}
		h.Swap(i, j)
        // 交换父节点和子节点
		i = j
        
	}
	return i > i0
}

up()函数是从下向上调整的过程,将j节点与其父节点比较,若满足小根堆的根值小于孩子值,就交换。

注意,up()函数不考虑兄弟节点,只要自己比父亲小,就可以交换。

func up(h Interface, j int) {
   
	for {
   
		i := (j - 1) / 2 // parent
		if i == j || !h.Less(j, i) {
   
			break
		}
		h.Swap(i, j)
		j = i
	}
}

结合上图 init()函数就是从非叶节点开始,逆序调整节点,构建堆heap


// The complexity is O(n) where n = h.Len().
fun
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值