package heap
import (
"encoding/json"
"fmt"
"testing"
)
/*
什么时候需要手写堆,需要更新堆中的某些值,让他自然有序
迪杰斯特拉算法 就需要这类算法
从每个节点扫一遍, 代价会非常高
用户:可能对于某一个已经存在的对象,修改值, 在堆上找到,调整到该去的位置,logN级别
*/
type MyHeap struct {
heap []interface{}
indexMap map[interface{}]int //任何一个样本,记录在堆上的位置
heapSize int
comparator func(a, b interface{}) bool //比大小
}
func (my *MyHeap)String() string {
byt,_ := json.MarshalIndent(my.heap,"\t"," ")
return string(byt)
}
func NewMyHeap(com func(a, b interface{}) bool ) *MyHeap {
return &MyHeap{
heap: []interface{}{},
indexMap: map[interface{}]int{},
heapSize: 0,
comparator: com,
}
}
func (my *MyHeap) IsEmpty() bool {
return my.heapSize == 0
}
func (my *MyHeap) Size() int {
return my.heapSize
}
func (my *MyHeap)contains(key interface{}) bool {
_, ok := my.indexMap[key]
return ok
}
func (my *MyHeap)push(value interface{}) {
my.heap = append(my.heap, value)
my.indexMap[value] = my.heapSize
my.heapInsert(my.heapSize)
my.heapSize++
}
func (my *MyHeap)pop() interface{} {
ans := my.heap[0]
end := my.heapSize - 1
my.swap(0,end)
my.heap = my.heap[0:end]
delete(my.indexMap,ans)
my.heapSize--
my.heapify(0,my.heapSize)
return ans
}
func (my *MyHeap)heapInsert(index int){
for my.comparator(my.heap[index],my.heap[(index -1) /2]) {
my.swap(index,(index - 1) / 2)
index = (index - 1) / 2
}
}
func (my *MyHeap)resign(val interface{}) {
valueIndex := my.indexMap[val]
my.heapInsert(valueIndex) //上行或下行,两个分支 只会中一个
my.heapify(valueIndex,my.heapSize) //都不中就出去,可以实现重复加入值,按引用传递的话
}
func (my *MyHeap)heapify(index, heapSize int) {
leftChild := 2 * index + 1
for leftChild < heapSize {
best := leftChild //下沉
if leftChild + 1 < heapSize && my.comparator(my.heap[best + 1], my.heap[best]) {
best = leftChild + 1
}
if !my.comparator(my.heap[best],my.heap[index]) {
break
}
my.swap(index,best)
index = best
leftChild = 2 *index + 1
}
}
func (my *MyHeap)swap(i, j int) { //强同步
my.heap[i], my.heap[j] = my.heap[j],my.heap[i]
my.indexMap[my.heap[i]],my.indexMap[my.heap[j]] = my.indexMap[my.heap[j]],my.indexMap[my.heap[i]]
}
type student struct {
Name string
Age int
Height int
Weight int
}
func TestMyHeap(t *testing.T) {
heap := NewMyHeap(func(a, b interface{}) bool { // 条件要统一
if a == b {
return false
}
A, B := a.(*student),b.(*student)
if A.Age < B.Age {
return true
}
if A.Age == B.Age {
return A.Height > B.Height //年龄相同根据身高排序
}
return false // a.Age < b.Age
})
students := []*student{
{
Name: "五零",
Age: 50,
Height: 190,
Weight: 130,
},
{
Name: "张三",
Age: 40,
Height: 160,
Weight: 100,
},
{
Name: "李四",
Age: 15,
Height: 100,
Weight: 110,
},
{
Name: "王五",
Age: 19,
Height: 190,
Weight: 190,
},
{
Name: "李六",
Age: 19,
Height: 180,
Weight: 170,
},
}
heap.push(students[0])
heap.push(students[1])
heap.push(students[2])
heap.push(students[3])
heap.push(students[4])
students[0].Age = 35
students[0].Name = "XXOO"
heap.resign(students[0]) //中途修改了某个值
//fmt.Println(heap)
for !heap.IsEmpty() {
fmt.Println(heap.pop())
}
}
堆定制——2.0过度泛化版
于 2021-10-24 16:36:39 首次发布