二叉堆是完全二叉树或者近似完全二叉树,又分为最大堆和最小堆。
本文实现的是最大堆, 最大堆的父节点一定大于其左右孩子节点,根节点是堆顶,也是堆中最大的元素。

以数组形式实现二叉堆,数组索引的特点如下:

  • 索引为i的左孩子的索引是 (2*i+1);
  • 索引为i的左孩子的索引是 (2*i+2);
  • 索引为i的父结点的索引是 floor((i-1)/2);

代码如下:

package main

type Heap struct {
    a []int
    n int
    count int
}

func NewHeap(capacity int) *Heap  {
    heap := &Heap{}
    heap.n = capacity
    heap.a = make([]int, capacity+1)
    heap.count = 0
    return heap
}

func (heap *Heap) Insert(data int) {
    if heap.count == heap.n { // 堆满
        return
    }
    heap.count++
    heap.a[heap.count] = data // 插入到最后

    // 与父节点比较,节点上浮
    i := heap.count
    parent := i / 2
    for parent > 0 && heap.a[parent] < heap.a[i] {
        heap.a[i], heap.a[parent] = heap.a[parent], heap.a[i]
        i = parent
        parent = i / 2
    }
}


// 删除最大元素(堆顶), 节点需要进行下沉操作
func (heap *Heap) removeMax() {
    if heap.count == 0 {
        return
    }

    // 最大元素和最后一个元素进行交换
    heap.a[1], heap.a[heap.count] = heap.a[heap.count], heap.a[i]
    heap.count--

    // 节点下沉
    heapifyUpDown(heap.a, heap.count)
}

func heapifyUpDown(a []int, count int)  {
    for i := 1; i <= count/2; {
        maxIdx := i
        if a[i] < a[i*2] {
            maxIdx = i * 2
        }
        if i * 2 + 1 <= count && a[maxIdx] < a[i*2+1] {
            maxIdx = i * 2 + 1
        }
        if maxIdx == i {
            break
        }
        a[i], a[maxIdx] = a[maxIdx], a[i]
        i = maxIdx
    }
}


func main() {

}