package heap
import (
"fmt"
"testing"
)
func TestHeap(t *testing.T) {
h := NewMyMaxHeap(10)
h.push(12)
h.push(32)
h.push(32)
h.push(392)
h.push(3922)
h.push(3002)
fmt.Println(h.Heap)
fmt.Println(h.pop())
fmt.Println(h.pop())
fmt.Println(h.pop())
fmt.Println(h.pop())
fmt.Println(h.pop())
fmt.Println(h.pop())
}
/*
堆结构
1.堆结构就是用数组实现的完全二叉树结构
2.完全二叉树中如果每棵子树的最大值都在顶部就是大根堆
3.完全二叉树中如果每棵子树的最小值都在顶部就是小根堆
4.堆结构的heapInsert与heapify操作
5.堆结构的增大和减小
6.优先队列结构,就是堆结构
完全二叉树 该层是满的 或 从左向右变满的状态中
1
/ \
2 3
/ \ / \
4 5 6 7
数组形式表示:
[ 1, 2, 3, 4, 5, 6, 7]
左孩子: 2*i + 1
右孩子: 2*i + 2
父节点: (i-1)/2
有的实现中 弃用0位置 从1 开始
左孩子: 2*i i << 1
有孩子: 2*i + 1 i << 1 + 1
父节点: i/2 i >> 2
使用位运算可能速度快?
堆:在完全二叉树上有其他要求,大根堆和小根对
*/
type MyMaxHeap struct {
Heap []int
Limit int
HeapSize int // 已经收集了多少个数,及其新来的数放在哪里
}
func NewMyMaxHeap(limit int) *MyMaxHeap {
return &MyMaxHeap{
Heap: make([]int,limit),
Limit: limit,
HeapSize: 0,
}
}
func (h *MyMaxHeap)isEmpty() bool {
return h.HeapSize == 0
}
func (h *MyMaxHeap)isFull() bool {
return h.HeapSize == h.Limit
}
func (h *MyMaxHeap)push(val int) { //高度 logN
if h.HeapSize == h.Limit {
return // 未加入错误处理,暂时return
}
h.Heap[h.HeapSize] = val
h.heapInsert()
h.HeapSize++
}
func (h *MyMaxHeap)heapInsert() {
for index := h.HeapSize; h.Heap[index] > h.Heap[ (index - 1 ) / 2 ]; index = (index - 1) / 2 { // 自己的值 > 父亲节点的值
h.Swap(index,(index- 1) / 2)
}
}
func (h *MyMaxHeap)pop() int {
if h.HeapSize == 0 {
return -1 //未加入错误处理,暂时用-1替代
}
ans := h.Heap[0]
h.HeapSize--
h.Swap(0,h.HeapSize) // 最后一个元素和第一个元素 交换
h.heapify(0) // 堆平衡 下沉操作
return ans
}
func (h *MyMaxHeap)heapify( index int) { // logN
left := index * 2 + 1 // 找到做孩子位置
for left < h.HeapSize { // 左孩子位置小于堆的size, 左孩子 >= 堆size 时,证明父节点没有孩子
largest := left // 左右孩子节点中选出一个大的
if (left + 1) < h.HeapSize && h.Heap[left + 1] > h.Heap[left] { // 有右孩子,并且右孩子比左孩子大
largest = left + 1
}
if h.Heap[largest] <= h.Heap[index] { // 如果寻找到的最大的孩子的值<= 父节点的值,证明父节点的位置刚刚好
break
}
h.Swap(index,largest) //下滑操作
index = largest // 当前节点作为父节点
left = index * 2 + 1 // 从当前节点继续下滑
}
}
func (h *MyMaxHeap) Swap(i, j int) {
if i == j { // 防清零
return
}
h.Heap[i] ^= h.Heap[j]
h.Heap[j] ^= h.Heap[i]
h.Heap[i] ^= h.Heap[j]
}
堆排序——大根堆
于 2021-10-23 22:12:10 首次发布