package main
import (
"fmt"
)
/*
* 使用最大堆实现排行榜功能(前N名排行榜)
*/
type InfoNode struct {
UserID int
Score int
}
type RankList struct {
MaxHeap []InfoNode
HeapSize int
UserNode map[int]int
}
func NewRankList() *RankList {
return &RankList{
UserNode: make(map[int]int),
}
}
func (r *RankList) UpdateUserScore(userID int, score int) {
i, exist := r.UserNode[userID]
if exist && score != r.MaxHeap[i].Score {
if score > r.MaxHeap[i].Score {
r.IncreaseScore(i, score)
} else {
r.DecreaseScore(i, score)
}
}
}
func (r *RankList) IncreaseScore(i int, score int) {
if score < r.MaxHeap[i].Score {
return
}
r.MaxHeap[i].Score = score
for i > 0 && r.MaxHeap[Parent(i)].Score < r.MaxHeap[i].Score {
r.MaxHeap[Parent(i)], r.MaxHeap[i] = r.MaxHeap[i], r.MaxHeap[Parent(i)]
r.UserNode[r.MaxHeap[Parent(i)].UserID] = Parent(i)
r.UserNode[r.MaxHeap[i].UserID] = i
i = Parent(i)
}
}
func (r *RankList) DecreaseScore(i int, score int) {
if score > r.MaxHeap[i].Score {
return
}
r.MaxHeap[i].Score = score
MaxHeapifyNode(r.MaxHeap, i, r.HeapSize)
}
func (r *RankList) Insert(node InfoNode) {
r.HeapSize++
r.MaxHeap = append(r.MaxHeap, node)
r.IncreaseScore(r.HeapSize-1, node.Score)
}
func (r *RankList) Output() []InfoNode {
heap := make([]InfoNode, r.HeapSize, r.HeapSize)
for i := 0; i < r.HeapSize; i++ {
heap[i] = r.MaxHeap[i]
}
heapsize := r.HeapSize
for i := r.HeapSize - 1; i > 0; i-- {
heapsize--
heap[0], heap[i] = heap[i], heap[0]
MaxHeapifyNode(heap, 0, heapsize)
}
return heap
}
func MaxHeapifyNode(A []InfoNode, i, heapsize int) {
largest := i
l := Left(i)
r := Right(i)
if l < heapsize && A[l].Score > A[largest].Score {
largest = l
}
if r < heapsize && A[r].Score > A[largest].Score {
largest = r
}
if largest != i {
A[largest], A[i] = A[i], A[largest]
MaxHeapifyNode(A, largest, heapsize)
}
}
func main() {
A := []int{3, 6, 9, 7, 8, 4, 2, 10}
fmt.Println(A)
rankList := NewRankList()
for i, score := range A {
rankList.Insert(InfoNode{
UserID: i + 1,
Score: score,
})
}
rankList.UpdateUserScore(3, 109)
rankList.UpdateUserScore(2, 106)
rankList.UpdateUserScore(8, 1)
B := rankList.Output()
for i := len(B) - 1; i >= 0; i-- {
fmt.Println(B[i])
}
}