优先队列
堆排序
排完序以后,就可以从队列里面取出想要的值。
// 最大堆、最小堆
// 接口实现比大小
type Item interface {
Less(than Item) bool
}
type Int int
func (x Int) Less(than Item) bool {
return x < than.(Int)
}
// 最小堆
type Heap struct {
// 数据
data []Item
// 是否最小值
min bool
// 锁
lock *sync.Mutex
}
// 初始化堆
func NewHeap() *Heap {
return &Heap{
data: make([]Item, 0),
min: true,
lock: new(sync.Mutex),
}
}
// 初始化最小堆
func NewMin() *Heap {
return &Heap{
data: make([]Item, 0),
min: true,
lock: new(sync.Mutex),
}
}
// 初始化最大堆
func NewMax() *Heap {
return &Heap{
data: make([]Item, 0),
min: false,
lock: new(sync.Mutex),
}
}
// 判断是否为空
func (h *Heap) isEmpty() bool {
return len(h.data) == 0
}
// 堆长度
func (h *Heap) Len() int {
return len(h.data)
}
// 获取数据
func (h *Heap) Get(index int) Item {
return h.data[index]
}
// 插入数据
func (h *Heap) Insert(it Item) {
h.lock.Lock()
defer h.lock.Unlock()
// 插入数据
h.data = append(h.data, it)
h.siftUp()
}
// 比较大小
func (h *Heap) Less(a, b Item) bool {
if h.min {
return a.Less(b)
} else {
return b.Less(a)
}
}
// 压缩,弹出一个
func (h *Heap) Extract() (el Item) {
h.lock.Lock()
defer h.lock.Unlock()
if h.Len() == 0 {
return
}
// 第一个
el = h.data[0]
// 最后一个
last := h.data[h.Len()-1]
// 如果只有一个数据
if h.Len() == 1 {
h.data = nil
return
}
// 排除了第一个
h.data = append([]Item{last}, h.data[1:h.Len()-1]...)
h.siftDown()
return
}
// 弹出一个极大值
func (h *Heap) siftUp() {
// 堆排序循环 n 2n+1
for i, parent := h.Len()-1, h.Len()-1; i > 0; i = parent {
// 顶点
parent = i / 2
// 对比子节点和顶点
if h.Less(h.Get(i), h.Get(parent)) {
h.data[parent], h.data[i] = h.data[i], h.data[parent]
} else {
break
}
}
}
// 弹出一个极小值
func (h *Heap) siftDown() {
// 堆排序循环 n 2n+1
for i, child := 0, 1; i < h.Len() && i*2+1 < h.Len(); i = child {
// 子结点
child = i*2 + 1
// 循环左右子结点
if child+1 <= h.Len()-1 && h.Less(h.Get(child+1), h.Get(child)) {
child++
}
// 对比顶点和子结点
if h.Less(h.Get(i), h.Get(child)) {
break
}
// 交换顶点和子结点的值
h.data[i], h.data[child] = h.data[child], h.data[i]
}
}
// 优先队列(基于堆)
type PriorityQueue struct {
// 数据
data *Heap.Heap
}
// 初始化优先队列(最大堆模式)
func NewMaxPriorityQueue() *PriorityQueue {
return &PriorityQueue{data: Heap.NewMax()}
}
// 初始化优先队列(最小堆模式)
func NewMinPriorityQueue() *PriorityQueue {
return &PriorityQueue{data: Heap.NewMin()}
}
// 优先队列项
type PriorityItem struct {
// 数据
value interface{}
// 优先级
level int
}
// 初始化优先队列项
func NewPriorityItem(value interface{}, level int) *PriorityItem {
return &PriorityItem{
value: value,
level: level,
}
}
// 比较优先级
func (x PriorityItem) Less(than Heap.Item) bool {
return x.level < than.(PriorityItem).level
}
// 队列的长度
func (pq *PriorityQueue) Len() int {
return pq.data.Len()
}
// 插入
func (pq *PriorityQueue) Insert(el PriorityItem) {
pq.data.Insert(el)
}
// 压缩
func (pq *PriorityQueue) Extract() PriorityItem {
return pq.data.Extract().(PriorityItem)
}
// 修改优先级
func (pq *PriorityQueue) ChangeLevel(val interface{}, level int) {
// 新队列
storage := NewQueue()
// 旧队列最小的值
popped := pq.Extract()
// 不等于传入值
for val != popped.value {
// 旧队列为空
if pq.Len() == 0 {
return
}
// 压入数据
storage.Push(popped)
// 数据处理
popped = pq.Extract()
}
// 找到该值
popped.level = level
// 插入数据
pq.data.Insert(popped)
// 其余数据重新放入优先队列
for storage.Len() > 0 {
pq.data.Insert(storage.Shift().(Heap.Item))
}