Golang实现最大堆/最小堆

参考: https://yangjiahao106.github.io/2019/01/15/golang-%E6%9C%80%E5%A4%A7%E5%A0%86%E5%92%8C%E6%9C%80%E5%B0%8F%E5%A0%86/
https://studygolang.com/articles/24288

方法一

此方法就是比较传统、常见的方法,下面来构建一个最小堆:

type Heap struct {
	Size int
	Elems []int
}

func NewHead(maxSize int) *Heap {
	//minHead := new(Heap)
	//minHead.Elems = make([]int, maxSize, maxSize)
	//return minHead
	minHead := Heap{Size: -1, Elems: make([]int, maxSize, maxSize)}
	return &minHead
}

func (h *Heap) Push(x int)  {
	if h.Size == len(h.Elems) - 1 {
		return
	}
	
	h.Size++
	i := h.Size
	// 与父节点进行比较,如果小于父节点,则向上冒泡;否则,停止;
	for i > 0 {
		parent := (i - 1) / 2
		if h.Elems[parent] <= x {
			break
		}
		h.Elems[i] = h.Elems[parent]
		i = parent
	}
	h.Elems[i] = x
}

func (h *Heap) Pop() int {
	if h.Size < 0 {
		return math.MinInt32
	}

	ret := h.Elems[0]
	// 将最后一个节点提到根节点,然后向下交换
	x := h.Elems[h.Size]
	i := 0
	for {
		l := 2*i + 1
		r := 2*i + 2

		if l >= h.Size {
			break
		}

		if r < h.Size && h.Elems[l] > h.Elems[r] {
			l = r
		}

		if x <= h.Elems[l] {
			break
		}

		h.Elems[i] = h.Elems[l]
		i = l
	}
	h.Size--
	h.Elems[i] = x
	return ret
}

测试:

func main() {
	minHead := NewHead(10)
	minHead.Push(2)
	minHead.Push(7)
	minHead.Push(5)
	minHead.Push(5)
	minHead.Push(4)
	minHead.Push(8)
	minHead.Push(8)
	minHead.Push(8)
	minHead.Push(8)
	minHead.Push(12)
	minHead.Push(20)

	k := minHead.Pop()
	for k != math.MinInt32 {
		fmt.Println(k)
		k = minHead.Pop()
	}
}

/* output:
		2
		4
		5
		5
		7
		8
		8
		8
		8
		12
*/

一些其他的操作,可以在此基础进行扩充。

方法二

container/heapheapheapheap
type Interface interface {
	sort.Interface
	Push(x interface{}) // add x as element Len()
	Pop() interface{}   // remove and return element Len() - 1.
}

// sort.Interface
type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
}
Less(i, j int) boolsort.go
if data.Less(m1, m0) {
	data.Swap(m1, m0)
}
Less()data[i]data[j]
type minHeap []int

func (h minHeap) Len() int {
	return len(h)
}

// 这里实现了小根堆,如果想要实现大根堆可以改为 h[i] > h[j]
func (h minHeap) Less(i, j int) bool {
	return h[i] < h[j]
}

func (h *minHeap) Swap(i, j int)  {
	(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}

func (h *minHeap) Push(x interface{})  {
	*h = append(*h, x.(int))
}

func (h *minHeap) Pop() interface{} {
	res := (*h)[len(*h) - 1]
	*h = (*h)[:len(*h) - 1]
	return res
}

测试:

func main() {
	h := make(minHeap, 0)
	heap.Init(&h)

	heap.Push(&h, 2)
	heap.Push(&h, 7)
	heap.Push(&h, 5)
	heap.Push(&h, 5)
	heap.Push(&h, 4)
	heap.Push(&h, 6)

	for len(h) != 0 {
		fmt.Println(heap.Pop(&h))
	}
}

/*output:
		2
		4
		5
		5
		6
		7
*/