优先级队列的底层实现是堆(最大堆、最小堆)
一、堆的特点
- 完全二叉树
- 每个节点的值都必须大于等于或小于等于子树中节点的值(对应最大堆、最小堆)
- 往堆中插入和删除一个元素的时间复杂度都是O(logn)
二、实现
最大堆和最小堆实现原理基本一样,下面实现一个最大堆
package main
type MaxHeap struct {
array []int //数组,从下标1开始存储数据
count int //堆中已经存储的数据个数
size int
}
//初始化一个堆
func NewMaxHeap(size int) *MaxHeap {
obj := &MaxHeap{
size: size,
count: 0,
array: make([]int, size),
}
return obj
}
//往堆中添加一个元素
func (this *MaxHeap) Push(data int) bool {
if this.count >= this.size {
return false
}
this.array[this.count] = data
i := this.count
this.dowToUp(i)
this.count++
return true
}
//移除堆顶元素
func (this *MaxHeap) Pop() int {
if this.count == 0 {
return -1 //堆中没有数据
}
max := this.array[0]
this.array[0] = this.array[this.count-1] //将最后一个元素放到堆顶
this.count--
this.upToDown(0) //堆化
return max
}
//获取当前存储元素的个数
func (this *MaxHeap) Count() int {
return this.count
}
//从下往上堆化
func (this *MaxHeap) dowToUp(i int) {
for (i-1)/2 >= 0 && this.array[i] > this.array[(i-1)/2] {
this.swap(i, (i-1)/2)
i = (i - 1) / 2
}
}
//自上往上堆化
func (this *MaxHeap) upToDown(i int) {
for {
a := this.array
n := this.count
maxPos := i
leftNode := i*2 + 1
rightNode := i*2 + 2
if leftNode < n && a[i] < a[leftNode] {
maxPos = leftNode
}
if rightNode < n && a[maxPos] < a[rightNode] {
maxPos = rightNode
}
if maxPos == i {
break
}
this.swap(i, maxPos)
i = maxPos //再检测子节点
}
}
func (this *MaxHeap) swap(i int, j int) {
this.array[i], this.array[j] = this.array[j], this.array[i]
}
这个最大堆本质就是一个优先级从高到低的队列,下面是测试
func main() {
//待入队元素
a := []int{8, 7, 6, 9, 0, 5, 1, 2, 3, 4}
//new一个优先级队列
priorityQueue := NewMaxHeap(len(a))
for i := 0; i < len(a); i++ {
priorityQueue.Push(a[i]) //依次入队
}
//依次出队
for priorityQueue.Count() > 0 {
fmt.Print(priorityQueue.Pop(), " ")
}
}
输出
9 8 7 6 5 4 3 2 1 0
三、堆排序
1.每次将堆中最大的元素移到数组的末尾
2.剩下n-1个元素重新堆化
3.重复到此过程至下标1的元素
func NewMaxHeadByArray(a []int) *MaxHeap {
n := len(a)
obj := &MaxHeap{
array: a,
count: n,
size: n,
}
//堆化
for i := n / 2; i >= 0; i-- {
obj.upToDown(i)
}
return obj
}
//堆排序
func MaxHeapSort(a []int) {
heap := NewMaxHeadByArray(a)
for heap.count > 0 {
//将最大的元素移到数组最后
heap.array[0], heap.array[heap.count-1] = heap.array[heap.count-1], heap.array[0]
//减少堆的长度
heap.count--
//堆顶元素改变,重新堆化,保持堆的特性
heap.upToDown(0)
}
}
测试
func main() {
//待入队元素
a := []int{8, 7, 6, 9, 0, 5, 1, 2, 3, 4}
MaxHeapSort(a)
fmt.Println(a)
}
输出
[0 1 2 3 4 5 6 7 8 9]
堆排序的复杂度为O(nLogn)
原文地址:https://www.cnblogs.com/chenqionghe/p/12161365.html
时间: 2024-11-02 17:12:47