二叉堆

结构:

    完全二叉树

分类

    大根堆:以任意节点作为根节点的树中的最大值就是根节点

    小跟堆:以任意节点作为根节点的树中的最小值就是根节点

基本操作

    heapInsert:向上调整

    heapIfy:向下调整

    heapPop:删除并返回堆顶元素

实现原理

    因为是一颗完全二叉树,所以采用数组实现。如果一个节点位置索引为i,父节点为:(i-1) / 2,左孩子:2*i +1 ,右孩子:2*i + 2

具体实现(默认实现的是小根堆)

func heapInsert(heap Interface, pos int) {

	posSelf := pos
	posPare := (pos - 1) / 2

	for {
		if !heap.Less(posSelf, posPare) {
			break
		}

		heap.Swap(posPare, posSelf)
		posSelf = posPare
		posPare = (posSelf - 1) / 2
	}
}

向上调整:当某个节点的元素值小于父节点时,和父节点交换,重复直到节点值不小于父节点或者当前节点已经是堆的根节点。

0的父节点还是0,利用这个特性,可以把两个边界条件整合成一个,即:当改节点小于父节点的时候就进行交换,否则就退出。

func heapIfy(heap Interface, pos int) {

	size := heap.Len()
	posSelf := pos
	posLeft := posSelf*2 + 1
	posRight := posSelf*2 + 2

	var minPos int
	for {
		if posLeft >= size {
			break
		}

		if posRight < size {

			if heap.Less(posLeft, posRight) {
				minPos = posLeft
			} else {
				minPos = posRight
			}
		} else {
			minPos = posLeft
		}

		if heap.Less(posSelf, minPos) {
			break
		}

		heap.Swap(minPos, posSelf)
		posSelf = minPos
		posLeft = posSelf*2 + 1
		posRight = posSelf*2 + 2
	}

}

向下调整:两个边界条件,1:该节点小于其两个子节点,2:该节点是叶节点。所以程序中上来首先判断是否为叶节点,如果是叶节点则无需向下调整,直接退出。如果不是叶节点,那么找出两个孩子中较小的一个(可能无右孩子,分情况讨论),如果较小的节点小于父节点则交换并重复,否则直接退出。

func heapPop(heap Interface) interface{} {

	var ret interface{}

	if heap.Len() > 0 {
		ret = heap.FirstElem()
	}

	if ret != nil {
		heap.Swap(0, heap.Len()-1)
		heap.DeleteLast()
		heapIfy(heap, 0)
	}

	return ret
}
删除堆顶并返回:如果堆为空,直接返回Nil,否则交换堆顶和堆的最后一个元素,然后删除最后一个元素,堆顶位置的元素做一个heapIfy的过程即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值