Sling Academy
Home/Golang/Exploring Priority Queues Using the `container/heap` Package in Go

Exploring Priority Queues Using the `container/heap` Package in Go

Last updated: November 26, 2024

The container/heap package in Go provides a convenient means to implement a priority queue, which is a data structure where each element has a priority. Elements are dequeued in order of their priority, rather than in simple insertion order. In Go, you can create a priority queue by defining a heap interface and using the functions provided in this package to maintain the heap properties.

Understanding the Heap Interface

To start with, you need to define a type that implements the heap.Interface, which is comprised of three functions: Len(), Less(i, j int) bool, Swap(i, j int), in addition to the methods Push(x interface{}) and Pop() interface{}.

package main

import (
    "container/heap"
    "fmt"
)

// An Item is something we manage in a priority queue.
type Item struct {
    value    string // The value of the item; arbitrary.
    priority int    // The priority of the item in the queue.
    index    int    // The index of the item in the heap.
}

// A PriorityQueue implements heap.Interface and holds Items.
type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
    // We want Pop to give us the highest, not lowest, priority so we use greater than here.
    return pq[i].priority > pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].index = i
    pq[j].index = j
}

func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    item := x.(*Item)
    item.index = n
    *pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    old[n-1] = nil  // avoid memory leak
    item.index = -1 // for safety
    *pq = old[0 : n-1]
    return item
}

Using the Priority Queue

Once you've implemented the interface, you can start using your priority queue. You'll want to use the heap functions heap.Init, heap.Push, and heap.Pop to manipulate your priority queue.

func main() {
    // Some items and their priorities.
    items := map[string]int{
        "banana": 3, "apple": 4, "pear": 2,
    }

    // Create a priority queue, put the items in it, and
    // establish the priority queue (heap) invariants.
    pq := make(PriorityQueue, len(items))
    i := 0
    for value, priority := range items {
        pq[i] = &Item{
            value:    value,
            priority: priority,
            index:    i,
        }
        i++
    }
    heap.Init(&pq)

    // Insert a new item and then modify its priority.
    item := &Item{
        value:    "orange",
        priority: 1,
    }
    heap.Push(&pq, item)

    pq.update(item, item.value, 5)

    // Take the items out; they arrive in decreasing priority order.
    for pq.Len() > 0 {
        item := heap.Pop(&pq).(*Item)
        fmt.Printf("%s with priority %d\n", item.value, item.priority)
    }
}

// update modifies the priority and value of an Item in the queue.
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
    item.value = value
    item.priority = priority
    heap.Fix(pq, item.index)
}

Conclusion

Using the container/heap package, you can efficiently maintain a priority queue tailored to your application's needs. This package significantly simplifies the creation and management of heaps in Go, offering a robust foundation for priority queue operations.

Next Article: Working with Template Engines Using the `text/template` and `html/template` Packages

Previous Article: Building In-Memory Lists with the `container/list` Package in Go

Series: Working with Core package in Go

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant