实现双端优先队列的Golang程序

实现双端优先队列的Golang程序

双端优先队列(Double Ended Priority Queue,简称DEPQ)是一种扩展了标准优先队列功能的数据结构。在本文中,我们将使用两种方法在Golang中实现双端优先队列:第一种方法使用两个单独的堆来处理最大和最小优先级,而第二种方法则在单个堆上增加额外的信息以实现高效的查询操作。在代码示例中,我们将执行插入、检索、删除和更新等操作。

解释

双端优先队列是一种允许插入和删除操作的数据结构,同时可以高效地访问集合中的最大和最小元素。

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结构包含两个切片:堆用于存储优先级队列中的元素,而值用于跟踪元素的位置。增强堆结构包含堆切片,可以高效查询最高优先级和最低优先级的元素。

示例1

在这个示例中,我们使用两个单独的堆(maxHeap和minHeap)来实现Go中的双端优先级队列。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

现实生活中的应用

医院患者管理

在医院中,患者分诊是根据其医疗状况进行优先级排序的过程。双端优先队列可以将病情最严重的患者存储在顶部(使用最大堆),而病情较轻的患者存储在底部(使用最小堆)。这使得医生可以快速处理重症患者,同时也能高效管理较不紧急的病例。

社交媒体动态

社交媒体平台通常根据用户参与度显示帖子。双端优先队列可以根据最高点赞或评论数将帖子优先排在顶部(使用最大堆),将不太受欢迎的帖子排在底部(使用最小堆)。这使用户可以在动态中看到热门内容和不太突出的帖子,提升他们的浏览体验。

结论

双端优先队列是标准优先队列的扩展,允许高效地检索最高和最低优先级的元素。在本文中,我们将探讨在go语言中实现双端优先队列的两种方法。第一种方法使用两个单独的堆来处理最大和最小优先级,而第二种方法则利用一个增强的堆。代码示例演示了在双端优先队列中插入、删除和检索元素的过程,展示了它们的实际应用和效率。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程