Go语言实现双端优先队列程序
双端优先队列(简称DEPQ)是一种扩展了标准优先队列功能的数据结构。在本文中,我们将使用两种方法在Go语言中实现双端优先队列:第一种方法使用两个独立的堆分别表示最大优先级和最小优先级;第二种方法则通过在单个堆中添加额外信息来高效地进行查询。在代码示例中,我们将执行插入、检索、删除和更新等操作。
解释
双端优先队列是一种允许插入和删除操作,并能高效访问集合中最大和最小元素的数据结构。
Max Heap: Min Heap: 9 3 / \ / \ 7 5 4 6 / / 3 5
在大顶堆中,根节点包含最大值[9],每个父节点的值都大于子节点的值,从上到下值递减。
在小顶堆中,根节点包含最小值[3],每个父节点的值都小于子节点的值,从上到下值递增。
算法
初始化两个堆,maxHeap和minHeap。
将元素与maxHeap和minHeap的根节点进行比较,以确定其优先级。将元素插入到相应的堆中。如果堆的大小差超过1,则平衡堆。
从包含该元素的堆中删除该元素。如果堆的大小差超过1,则平衡堆。
返回maxHeap的根节点。
返回minHeap的根节点。
语法
type DEPQ struct {
maxHeap, minHeap []int
}
DEPQ结构体包含maxHeap和minHeap切片,允许高效地检索最高和最低优先级元素。
type DEPQ struct {
heap []int
values map[int]int
}
该语法使用单个增强堆来实现DEPQ。DEPQ结构体包含两个切片:heap用于存储优先队列中的元素,values用于跟踪元素的位置。AugmentedHeap结构体包含heap切片,允许高效地查询最高和最低优先级元素。
示例1
在这个例子中,我们使用两个独立的堆在Go语言中实现双端优先队列,一个用于最大优先级(maxHeap),另一个用于最小优先级(minHeap)。Insert函数将元素插入到两个堆中,而Delete函数则从两个堆中删除元素。GetMax和GetMin函数分别从DEPQ中检索最大和最小元素。
package main
import (
"container/heap"
"fmt"
)
type MaxHeap []int
func (h MaxHeap) Len() int { return len(h) }
func (h MaxHeap) Less(i, j int) bool { return h[i] > h[j] }
func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MaxHeap) Push(x interface{}) { *h = append(*h, x.(int)) }
func (h *MaxHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type MinHeap []int
func (h MinHeap) Len() int { return len(h) }
func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *MinHeap) Push(x interface{}) { *h = append(*h, x.(int)) }
func (h *MinHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type DEPQ struct {
maxHeap *MaxHeap
minHeap *MinHeap
}
func NewDEPQ() *DEPQ {
maxHeap := &MaxHeap{}
minHeap := &MinHeap{}
heap.Init(maxHeap)
heap.Init(minHeap)
return &DEPQ{maxHeap, minHeap}
}
func (dq *DEPQ) Insert(val int) {
heap.Push(dq.maxHeap, val)
heap.Push(dq.minHeap, val)
}
func (dq *DEPQ) Delete(val int) {
for i := 0; i < len(*dq.maxHeap); i++ {
if (*dq.maxHeap)[i] == val {
heap.Remove(dq.maxHeap, i)
break
}
}
for i := 0; i < len(*dq.minHeap); i++ {
if (*dq.minHeap)[i] == val {
heap.Remove(dq.minHeap, i)
break
}
}
}
func (dq *DEPQ) GetMax() int {
if len(*dq.maxHeap) > 0 {
return (*dq.maxHeap)[0]
}
return -1
}
func (dq *DEPQ) GetMin() int {
if len(*dq.minHeap) > 0 {
return (*dq.minHeap)[0]
}
return -1
}
func main() {
dq := NewDEPQ()
dq.Insert(5)
dq.Insert(3)
dq.Insert(7)
dq.Insert(4)
dq.Insert(6)
fmt.Println("Maximum element:", dq.GetMax())
fmt.Println("Minimum element:", dq.GetMin())
dq.Delete(4)
fmt.Println("Maximum element after deletion:", dq.GetMax())
fmt.Println("Minimum element after deletion:", dq.GetMin())
}
输出
Maximum element: 7 Minimum element: 3 Maximum element after deletion: 7 Minimum element after deletion: 3
示例2
在这个例子中,我们使用单个堆来表示Go语言中的双端优先队列。每个元素在堆中存储两次,一次作为最大元素,一次作为最小元素,使用DEPQNode结构体。DEPQ结构体包含堆和一个唯一标识符,以确保每个节点都有一个独特的标识符。Insert函数通过创建两个DEPQNode实例(一个用于最大值,一个用于最小值)并将它们添加到堆中来向DEPQ添加元素。GetMaximum和GetMinimum函数分别从DEPQ中检索最大和最小元素。Remove函数通过查找和删除堆中元素的两个实例来从DEPQ中删除指定元素。
package main
import (
"container/heap"
"fmt"
)
type DEPQNode struct {
value int
isMax, isMin bool
uniqueID int
}
type DEPQHeap []DEPQNode
func NewDEPQHeap() *DEPQHeap {
return &DEPQHeap{}
}
func (h DEPQHeap) Len() int { return len(h) }
func (h DEPQHeap) Less(i, j int) bool { return h[i].value < h[j].value }
func (h DEPQHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *DEPQHeap) Push(x interface{}) {
node := x.(DEPQNode)
*h = append(*h, node)
}
func (h *DEPQHeap) Pop() interface{} {
old := *h
n := len(old)
node := old[n-1]
*h = old[0 : n-1]
return node
}
type DoubleEndedPriorityQueue struct {
heap *DEPQHeap
}
func NewDoubleEndedPriorityQueue() *DoubleEndedPriorityQueue {
return &DoubleEndedPriorityQueue{
heap: NewDEPQHeap(),
}
}
func (dePQ *DoubleEndedPriorityQueue) Insert(value int) {
node := DEPQNode{value: value, isMax: true, isMin: true, uniqueID: len(*dePQ.heap)}
heap.Push(dePQ.heap, node)
}
func (dePQ *DoubleEndedPriorityQueue) GetMinimum() int {
if dePQ.heap.Len() == 0 {
return -1
}
return (*dePQ.heap)[0].value
}
func (dePQ *DoubleEndedPriorityQueue) GetMaximum() int {
if dePQ.heap.Len() == 0 {
return -1
}
return (*dePQ.heap)[dePQ.heap.Len()-1].value
}
func main() {
dePQ := NewDoubleEndedPriorityQueue()
dePQ.Insert(10)
dePQ.Insert(5)
dePQ.Insert(20)
fmt.Println("Minimum Element:", dePQ.GetMinimum())
fmt.Println("Maximum Element:", dePQ.GetMaximum())
}
输出
Minimum Element: 5 Maximum Element: 20
现实生活中的应用
医院病人管理
在医院中,病人分诊涉及根据病人的病情优先安排病人。DEPQ可以存储病情最严重的病人(使用大顶堆)和病情较轻的病人(使用小顶堆)。这使得医生能够快速处理危重病人,同时有效地管理不太紧急的病例。
社交媒体信息流
社交媒体平台通常根据用户参与度显示帖子。DEPQ可以优先显示点赞或评论最多的帖子(使用大顶堆)以及不太受欢迎的帖子(使用小顶堆)。这允许用户在信息流中看到热门内容和不太突出的帖子,从而增强他们的浏览体验。
结论
DEPQ是标准优先队列的扩展,允许高效地检索最高和最低优先级元素。在本文中,我们将探讨两种在Go语言中实现双端优先队列的方法。第一种方法使用两个独立的堆分别表示最大和最小优先级,而第二种方法则使用单个增强堆。代码示例演示了DEPQ中元素的插入、删除和检索,展示了它们的实际应用和效率。
数据结构
网络
关系数据库管理系统 (RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP