优先队列

博客介绍了队列先进先出的特性,指出优先队列不遵循此原则。并说明了使用最大堆来实现最大优先队列,涉及Golang相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是队列

通过上面的链接,我们可以知道什么是一般的队列,它的特性就是先进先出

但这里的优先队列不再遵循先进先出的原则,而是分为两种情况:

最大优先队列:无论入队顺序如何,都是当前最大的元素优先出列
最小优化队列:无论入队顺序如何,都是当前最小的元素优先出列

这里用最大堆实现最大优先队列,如下:

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)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值