From 2b881acc2825dca8b2a8c0c2de70b6927f7a83ce Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Sat, 16 Jan 2021 17:17:29 +0100 Subject: [PATCH] Add min-heap --- heap.lua | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ init.lua | 3 ++- test.lua | 15 +++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 heap.lua diff --git a/heap.lua b/heap.lua new file mode 100644 index 0000000..5475541 --- /dev/null +++ b/heap.lua @@ -0,0 +1,50 @@ +local metatable = {__index = getfenv(1)} + +function default_less_than(a, b) return a < b end + +--> empty min heap +function new(less_than) + return setmetatable({less_than = less_than or default_less_than}, metatable) +end + +function push(self, value) + table.insert(self, value) + local function heapify(index) + if index == 1 then + return + end + local parent = math.floor(index / 2) + if self.less_than(self[index], self[parent]) then + self[parent], self[index] = self[index], self[parent] + heapify(parent) + end + end + heapify(#self) +end + +function pop(self) + local value = self[1] + local last = #self + if last == 1 then + self[1] = nil + return value + end + self[1], self[last] = self[last], nil + last = last - 1 + local function heapify(index) + local left_child = index * 2 + if left_child > last then + return + end + local smallest_child = left_child + 1 + if smallest_child > last or self.less_than(self[left_child], self[smallest_child]) then + smallest_child = left_child + end + if self.less_than(self[smallest_child], self[index]) then + self[index], self[smallest_child] = self[smallest_child], self[index] + heapify(smallest_child) + end + end + heapify(1) + return value +end \ No newline at end of file diff --git a/init.lua b/init.lua index 10276e6..7210a8e 100644 --- a/init.lua +++ b/init.lua @@ -68,7 +68,8 @@ for _, component in ipairs{ "text", "vector", "minetest", - "trie" + "trie", + "heap" } do modlib[component] = loadfile_exports(get_resource(component .. ".lua")) end diff --git a/test.lua b/test.lua index 89e656a..3cf6e2c 100644 --- a/test.lua +++ b/test.lua @@ -54,4 +54,19 @@ if tests.liquid_raycast then end end end) +end + +local n = 100 +local list = {} +for index = 1, n do + list[index] = index +end +modlib.table.shuffle(list) +local heap = modlib.heap.new() +for index = 1, #list do + heap:push(list[index]) +end +for index = 1, #list do + local popped = heap:pop() + assert(popped == index) end \ No newline at end of file