- Lua Game Development Cookbook
- Mário Ka?uba
- 690字
- 2021-07-16 13:23:06
Making a prioritized queue
A prioritized queue or simple priority queue extends basic queue with the entry sorting feature. Upon entry insertion, you can set what will be the priority of the entry. This data structure is often used in job queuing where the most important (highest priority) jobs must be processed before the jobs with lower priority. Priority queues are often used in artificial intelligence as well.
This version of the prioritized queue allows you to obtain entries with minimal or maximal priority at constant time. Element priority can be updated. However, priority queue insertion, update, and removal might use linear time complexity in worst case scenarios.
There are two rules that should be noted:
- Each entry of this queue should be unique
- The order of retrieving elements with the same priority is not defined
Getting ready
This recipe will use the following shortcuts:
local ti = table.insert local tr = table.remove -- removes element from table by its value local tr2 = function(t, v) for i=1,#t do if t[i]==v then tr(t, i) break end end end
It's recommended to put it all together in one Lua module file.
How to do it…
The priority queue can be defined as in the following code:
return function pqueue() -- interface table local t = {} -- a set of elements local set = {} -- a set of priority bags with a elements local r_set = {} -- sorted list of priorities local keys = {} -- add element into storage, set its priority and sort keys -- k - element -- v - priority local function addKV(k, v) set[k] = v -- create a new list for this priority if not r_set[v] then ti(keys, v) table.sort(keys) local k0 = {k} r_set[v] = k0 setmetatable(k0, { __mode = 'v' }) -- add element into list for this priority else ti(r_set[v], k) end end -- remove element from storage and sort keys local remove = function(k) local v = set[k] local prioritySet = r_set[v] tr2(prioritySet, k) if #prioritySet < 1 then tr2(keys, v) r_set[v] = nil table.sort(keys) set[k] = nil end end; t.remove = remove -- returns an element with the lowest priority t.min = function() local priority = keys[1] if priority then return r_set[priority][1] or {} else return {} end end -- returns an element with the highest priority t.max = function() local priority = keys[#keys] if priority then return r_set[priority][1] or {} else return {} end end -- is this queue empty? t.empty = function() return #keys < 1 end -- simple element iterator, retrieves elements with -- the highest priority first t.iterate = function() return function() if not t.empty() then local element = t.max() t.remove(element) return element end end end -- setup pqueue behavior setmetatable(t, { __index = set, __newindex = function(t, k, v) if not set[k] then -- new item addKV(k, v) else -- existing item remove(k) addKV(k, v) end end, }) return t end
How it works…
This priority queue algorithm uses three tables: set
, r_set
, and keys
. These tables help to organize elements into so-called priority bags. The first one, set
contains elements paired with their priorities. It's also used when you try to obtain element priority from the queue. The second one, r_set
contains priority bags. Each bag represents a priority level. The last one keys
contains a sorted list of priorities, which is used in the extraction of elements from a minimal or maximal priority bag.
Each element can be inserted in a way similar to the Lua table with the exception that the inserted element is used as a key and priority
is stored as a value:
priority_queue[element] = priority
This form of access can be used to update element priority. Elements with minimal or maximal priority can be extracted using the min
or max
function respectively;
local min_element = priority_queue.min() local max_element = priority_queue.max()
Note that elements remain in the priority queue until you delete them with the remove
function;
priority_queue.remove(element)
Priority queue can be queried with the empty
function that returns true if there's no element in the queue;
priority_queue.empty()
You can use the iterator function in for
loop to process all queue elements sorted by their priority:
for element in priority_queue.iterator() do -- do something with this element end
- 多媒體CAI課件設(shè)計與制作導(dǎo)論(第二版)
- iOS面試一戰(zhàn)到底
- 程序員面試白皮書
- Azure IoT Development Cookbook
- Instant Zepto.js
- 動手玩轉(zhuǎn)Scratch3.0編程:人工智能科創(chuàng)教育指南
- Python語言程序設(shè)計
- 軟件測試項目實戰(zhàn)之性能測試篇
- Python貝葉斯分析(第2版)
- Linux:Embedded Development
- 移動界面(Web/App)Photoshop UI設(shè)計十全大補
- Mastering Concurrency in Python
- Yii2 By Example
- Java RESTful Web Service實戰(zhàn)
- Learning iOS Penetration Testing