-------------------------------------------------------------------------------- -- https://github.com/sysread/lua-skewheap -------------------------------------------------------------------------------- local VALUE = 1 local LEFT = 2 local RIGHT = 3 local function Node(value, left, right) return {value, left, right} end local function copy_node(n) return Node(table.unpack(n or {})) end local function merge(a, b) if not a then return copy_node(b) elseif not b then return copy_node(a) elseif b[VALUE] < a[VALUE] then return merge(b, a) else return Node(a[VALUE], merge(b, a[RIGHT]), a[LEFT]) end end -------------------------------------------------------------------------------- -- SkewHeap class -------------------------------------------------------------------------------- local SkewHeap = {} SkewHeap.__index = SkewHeap function SkewHeap.new() local self = {} setmetatable(self, SkewHeap) self.size = 0 self.root = nil return self end function SkewHeap:items() return self.size end function SkewHeap:is_empty() return self.size == 0 end function SkewHeap:put(...) for _, item in ipairs {...} do self.root = merge(self.root, Node(item, nil, nil)) self.size = self.size + 1 end return self.size end function SkewHeap:take(...) local count = 1 local items = {} if select('#', ...) > 0 then count = select(1, ...) end for _ = 1, count do if self.root then local item = self.root[VALUE] self.root = merge(self.root[LEFT], self.root[RIGHT]) self.size = self.size - 1 table.insert(items, item) else break end end return table.unpack(items) end function SkewHeap:peek() if not self.root then return else return self.root[VALUE] end end function SkewHeap:merge(other) local newheap = SkewHeap.new() newheap.root = merge(self.root, other.root) newheap.size = self.size + other.size return newheap end return SkewHeap