← Back to the index page

Priority queue

Priority queue is an abstract data type similar to queue and stack. The difference is that each element has a priority value. Values with higher priority are pulled first. There might be different implementations of handling priority.

Figure 01: Priority queue

Priority queue class

Here is a demonstration of the most simple using unsorted list class where the insertion time is O(1) and the pulling time is O(n).

There are different possible implementations:

ImplementationInsertPullPeek
Binary HeapO(log n)O(log n)O(1)
Fibonacci HeapO(1)1O(log n)1O(1)
Binary Search Tree (BST)2O(log n)O(log n)O(log n)
Unsorted List3O(n)O(n)O(1)
Sorted ListO(n)O(1)O(1)

Class implementation with OOP principles and annotations.

PriorityQueue.lua

---@class Node
---@field value any
---@field priority number
local Node = {}
Node.__index = Node

---@return Node
---@param value any
---@param priority number
function Node:new(value, priority)
    return setmetatable({
        priority = priority,
        value = value,
    }, self)
end

---@class PriorityQueue
local PriorityQueue = {}
PriorityQueue.__index = PriorityQueue

---@return PriorityQueue
function PriorityQueue:new()
    return setmetatable({}, self)
end

---@return number
function PriorityQueue:size()
    return #self
end

---@param value any
---@param priority? number
function PriorityQueue:insert(value, priority)
    priority = priority or 1
    self[#self + 1] = Node:new(value, priority)
end

---Pulls the value with the highest priority. If priority queue is empty
---then nil and zero are returned.
---@return any, number
function PriorityQueue:pull()
    if self:size() == 0 then
        return nil, 0
    end
    local node, idx = self:peek()
    table.remove(self, idx)
    return node.value, idx
end

---Retuns the last element with highest priority and its index.
---@return any, number
function PriorityQueue:peek()
    if self:size() == 0 then
        return nil, 0
    end
    local highestIndex = 1
    local highest = self[1]
    for i, node in ipairs(self) do
        if highest.priority < node.priority then
            highest = node
            highestIndex = i
        end
    end
    return highest.value, highestIndex
end

---@return string
function PriorityQueue:toString(sep)
    sep = sep or ","
    local t = {}
    for i in ipairs(self) do
        t[#t + 1] = "{" .. tostring(self[i].value) .. ", " .. self[i].priority .. "}"
    end
    return table.concat(t, sep)
end

return PriorityQueue

Usage of PriorityQueue class

local pq = PriorityQueue:new()
pq:insert("A", 1)
pq:insert("B", 2)
pq:insert("C", 4)
pq:insert("D", 3)
print(pq:pull()) --> "C"
print(pq:pull()) --> "D"
print(pq:peek()) --> "B"    2
print(pq:toString()) --> "{A, 1},{B, 2}"

References

← Back to the index page