通过上面的链接,我们可以知道什么是一般的队列,它的特性就是先进先出
但这里的优先队列不再遵循先进先出的原则,而是分为两种情况:
最大优先队列:无论入队顺序如何,都是当前最大的元素优先出列
最小优化队列:无论入队顺序如何,都是当前最小的元素优先出列
这里用最大堆实现最大优先队列,如下:
package main
/*
利用最大堆实现最大优先队列
*/
import "fmt"
type Queen struct {
slice []int
length int
}
// 最大堆尾节点的上浮操作(较大者上浮) O(logn)
func (m *Queen) upAdjust() {
if m.length <= 1 {
return //最多一个节点,不用操作
}
childIndex := m.length - 1 //尾节点索引
parentIndex := (childIndex - 1) / 2 //尾节点的父节点索引
temp := m.slice[childIndex]
for childIndex > 0 && temp > m.slice[parentIndex] {
m.slice[childIndex] = m.slice[parentIndex]
childIndex = parentIndex
parentIndex = (childIndex - 1) / 2
}
m.slice[childIndex] = temp
}
// 最大堆节点的下沉操作(较小者下沉) O(logn)
func (m *Queen) downAdjust(parentIndex int) {
temp := m.slice[parentIndex] //保存父节点的值,用于最后的赋值
childIndex := 2*parentIndex + 1 //获取左孩子节点索引
for childIndex < m.length { //存在左孩子
if childIndex+1 < m.length && m.slice[childIndex+1] > m.slice[childIndex] { //如果右孩子存在且小于左孩子,取右孩子的值。总之是取到最小孩子节点值
childIndex += 1
}
if temp > m.slice[childIndex] {
break //父节点小于最小孩子节点值,结束上浮操作
} else {
//完成一次下沉操作,再开始下一次
m.slice[parentIndex] = m.slice[childIndex]
parentIndex = childIndex
childIndex = 2*parentIndex + 1
}
}
m.slice[parentIndex] = temp
}
//获取最大优先队列长度
func (m *Queen) Length() int {
return m.length
}
//入列操作
func (m *Queen) enqueue(value int) {
m.slice = append(m.slice, value)
m.length++
m.upAdjust()
}
// 出列操作
func (m *Queen) dequeue() int {
if m.length == 0 {
panic("queen length = 0")
}
res := m.slice[0] //出列元素
m.slice[0] = m.slice[m.length-1] //将头节点替换成尾节点
m.slice = m.slice[:m.length-1] //删除原来的尾节点,相当于删除了头节点
m.length--
m.downAdjust(0) //将头节点执行一次下沉操作,使之保持最大堆
return res
}
//构建最大优先队列 O(n)
func (m *Queen) buildMaxHeap() {
for i := (len(m.slice) - 2) / 2; i >= 0; i-- {
//从最后一个非叶子节点开始,向上依次执行下沉操作
m.downAdjust(i)
}
}
//生成一个空队列
func NewQueen() Queen {
Queen := Queen{
slice: []int{},
length: 0,
}
return Queen
}
func main() {
Queen := NewQueen()
fmt.Println(Queen.slice) //打印空队列
Queen.enqueue(4)
fmt.Println(Queen.slice)
Queen.enqueue(6)
fmt.Println(Queen.slice)
Queen.enqueue(2)
fmt.Println(Queen.slice)
fmt.Println(Queen.dequeue())
fmt.Println(Queen.slice)
Queen.enqueue(3)
fmt.Println(Queen.slice)
fmt.Println(Queen.dequeue())
fmt.Println(Queen.slice)
}