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中元素的插入、删除和检索,展示了它们的实际应用和效率。

更新于:2023年9月5日

浏览量:147

开启你的职业生涯

完成课程获得认证

开始学习
广告
© . All rights reserved.