@heap-data-structure/binomial-heap
Version:
Binomial heap data structures for JavaScript
1 lines • 25.5 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/BinomialTree.js","../src/BinomialTreeWithParent.js","../src/LazyNode.js","../src/LazyStack.js","../src/BinomialHeap.js","../src/LazyBinomialHeap.js"],"sourcesContent":["export default function BinomialTree(value, children) {\n\tthis.value = value;\n\tthis.children = children;\n}\n\n/**\n * /!\\ Can only be used to merge two trees of the same rank.\n * /!\\ Modifies both trees\n */\n\nBinomialTree.prototype.merge = function (predicate, other) {\n\tif (predicate(this.value, other.value) <= 0) {\n\t\tthis.children = this.children.concat(other);\n\t\treturn this;\n\t}\n\n\tother.children = other.children.concat(this);\n\treturn other;\n};\n\n/**\n * Method used to reset a tree element in order to reuse it\n * somewhere else, e.g. insert it back in the same or a new\n * heap.\n */\n\nBinomialTree.prototype.detach = function () {\n\tthis.children.splice(0);\n\treturn this;\n};\n\nBinomialTree.prototype.setparent = function (_parent) {\n\t// We do not keep track of any parent here\n};\n","export default function BinomialTreeWithParent(value, children) {\n\tthis.value = value;\n\tthis.children = children;\n\tthis.parent = null;\n}\n\nBinomialTreeWithParent.prototype.rank = function () {\n\treturn this.children.length;\n};\n\n/**\n * /!\\ Can only be used to merge two trees of the same rank.\n * /!\\ Modifies both trees\n */\n\nBinomialTreeWithParent.prototype.merge = function (predicate, other) {\n\tif (predicate(this.value, other.value) <= 0) {\n\t\tthis.children = this.children.concat(other);\n\t\tother.parent = this;\n\t\treturn this;\n\t}\n\n\tother.children = other.children.concat(this);\n\tthis.parent = other;\n\treturn other;\n};\n\n/**\n * Method used to reset a tree element in order to reuse it\n * somewhere else, e.g. insert it back in the same or a new\n * heap.\n */\n\nBinomialTreeWithParent.prototype.detach = function () {\n\tthis.children.splice(0);\n\tthis.parent = null;\n\treturn this;\n};\n\nBinomialTreeWithParent.prototype.setparent = function (parent) {\n\tthis.parent = parent;\n};\n","export default function LazyNode(value, next) {\n\tthis.value = value;\n\tthis.next = next;\n}\n","import LazyNode from './LazyNode.js';\n\n/**\n * LazyStack#peek only valid if LazyStack#empty is false.\n * LazyStack#shift only valid if LazyStack#empty is false.\n */\n\nexport default function LazyStack() {\n\tthis.top = null;\n\tthis.bottom = null;\n}\n\nLazyStack.prototype.empty = function () {\n\treturn this.top === null;\n};\n\nLazyStack.prototype.push = function (value) {\n\tthis.top = new LazyNode(value, this.top);\n\n\tif (this.bottom === null) this.bottom = this.top;\n};\n\n/**\n * Only valid if LazyStack#empty is false.\n */\n\nLazyStack.prototype.pop = function () {\n\tconst value = this.top.value;\n\n\tthis.top = this.top.next;\n\n\tif (this.top === null) this.bottom = null;\n\n\treturn value;\n};\n\nLazyStack.prototype.meld = function (other) {\n\tif (this.bottom === null) this.top = other.top;\n\telse this.bottom.next = other.top;\n\n\tthis.bottom = other.bottom;\n};\n","export default function BinomialHeap(BinomialTree) {\n\tconst binomial_heap_push = function (compare, list, tree, rank) {\n\t\t// Ensures list has at least rank cells\n\n\t\tlet i = rank - list.length;\n\n\t\twhile (i-- > 0) {\n\t\t\tlist.push(null);\n\t\t}\n\n\t\t// Loop invariant\n\t\t// tree and list[i] have the same rank\n\n\t\tconst len = list.length;\n\n\t\tfor (i = rank; i < len && list[i] !== null; ++i) {\n\t\t\t// There is already a tree with this rank\n\n\t\t\ttree = tree.merge(compare, list[i]);\n\t\t\tlist[i] = null;\n\t\t}\n\n\t\t// Do not forget to append null if\n\t\t// we are lacking space\n\n\t\tif (i === len) {\n\t\t\tlist.push(null);\n\t\t}\n\n\t\t// Cell is empty\n\t\t// we can just put the new tree here\n\n\t\tlist[i] = tree;\n\t};\n\n\tconst merge = function (compare, list, other) {\n\t\tif (other.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Merging two binomial heaps is like\n\t\t// adding two little endian integers\n\t\t// so, we first make sure that we have\n\t\t// enough place to store the result\n\n\t\tlet i = other.length - list.length;\n\n\t\twhile (i-- > 0) {\n\t\t\tlist.push(null);\n\t\t}\n\n\t\tlet carry = null;\n\n\t\tconst len = list.length;\n\n\t\t// Remember len >= other.length\n\n\t\tfor (i = 0; i < len; ++i) {\n\t\t\t// Other[i] can be either null or not\n\t\t\t// list[i] can be either null or not\n\t\t\t// carry can be either null or not\n\t\t\t// --> 2^3 = 8 possibilities\n\t\t\t//\n\t\t\t// null ? | other[i] | list[i] | carry\n\t\t\t// ---------------------------------------\n\t\t\t// (0) | no | no | no\n\t\t\t// (1) | no | no | yes\n\t\t\t// (2) | no | yes | no\n\t\t\t// (3) | no | yes | yes\n\t\t\t// (4) | yes | no | no\n\t\t\t// (5) | yes | no | yes\n\t\t\t// (6) | yes | yes | no\n\t\t\t// (7) | yes | yes | yes\n\n\t\t\tif (i >= other.length || other[i] === null) {\n\t\t\t\tif (carry !== null) {\n\t\t\t\t\t// (6) other[i] = null and list[i] = null and carry != null\n\t\t\t\t\t// --> put carry in current cell\n\n\t\t\t\t\tif (list[i] === null) {\n\t\t\t\t\t\tlist[i] = carry;\n\t\t\t\t\t\tcarry = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// (4) other[i] = null and list[i] != null and carry != null\n\t\t\t\t\t// --> merge carry with current cell\n\t\t\t\t\telse {\n\t\t\t\t\t\tcarry = carry.merge(compare, list[i]);\n\t\t\t\t\t\tlist[i] = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// We do not need to do anything for\n\t\t\t\t// those 2 cases (carry and other[i] are null).\n\t\t\t\t// ==\n\t\t\t\t// (5) other[i] = null and list[i] != null and carry = null\n\t\t\t\t// (7) other[i] = null and list[i] = null and carry = null\n\t\t\t}\n\n\t\t\t// (0) other[i] != null and list[i] != null and carry != null\n\t\t\t// (2) other[i] != null and list[i] = null and carry != null\n\t\t\t// --> merge carry with other[i]\n\t\t\telse if (carry !== null) {\n\t\t\t\tcarry = carry.merge(compare, other[i]);\n\t\t\t}\n\n\t\t\t// (1) other[i] != null and list[i] != null and carry = null\n\t\t\t// --> merge current cell with other[i]\n\t\t\telse if (list[i] !== null) {\n\t\t\t\tcarry = list[i].merge(compare, other[i]);\n\t\t\t\tlist[i] = null;\n\t\t\t}\n\n\t\t\t// (3) other[i] != null and list[i] = null and carry = null\n\t\t\t// --> put other[i] in list\n\t\t\telse {\n\t\t\t\tlist[i] = other[i];\n\t\t\t}\n\t\t}\n\n\t\t// Do not forget to append last carry\n\n\t\tif (carry !== null) {\n\t\t\tlist.push(carry);\n\t\t}\n\t};\n\n\tconst find_min_index = function (compare, list, j, len) {\n\t\t// There MUST be at least one\n\t\t// non null element in this list\n\t\t// we look for the first one\n\n\t\tfor (; j < len - 1 && list[j] === null; ++j);\n\n\t\t// Here j is necessarily < len\n\t\t// and list[j] is non null\n\n\t\tlet i = j;\n\t\tlet opt = list[j].value;\n\n\t\t// We lookup remaining elements to see if there\n\t\t// is not a better candidate\n\n\t\tfor (++j; j < len; ++j) {\n\t\t\tconst item = list[j];\n\n\t\t\tif (item !== null) {\n\t\t\t\tconst candidate = item.value;\n\n\t\t\t\tif (compare(candidate, opt) < 0) {\n\t\t\t\t\ti = j;\n\t\t\t\t\topt = candidate;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn i;\n\t};\n\n\tconst remove_head_at_index = function (compare, list, i, len) {\n\t\tconst orphans = list[i].children;\n\t\tlist[i] = null;\n\n\t\tchange_parent(null, orphans);\n\n\t\t// We just removed the ith element\n\t\t// if list[i] is the last cell\n\t\t// of list we can drop it\n\n\t\tif (i === len - 1) {\n\t\t\tlist.pop();\n\t\t}\n\n\t\t// We merge back the children of\n\t\t// the removed tree into the heap\n\n\t\tmerge(compare, list, orphans);\n\t};\n\n\tconst binomial_heap_pop = function (compare, list) {\n\t\tconst len = list.length;\n\n\t\tconst i = find_min_index(compare, list, 0, len);\n\n\t\tconst tree = list[i];\n\n\t\tremove_head_at_index(compare, list, i, len);\n\n\t\treturn tree;\n\t};\n\n\tconst change_parent = function (parent, children) {\n\t\tconst len = children.length;\n\n\t\tfor (let i = 0; i < len; ++i) {\n\t\t\tchildren[i].setparent(parent);\n\t\t}\n\t};\n\n\tconst shift_up = function (tree, parent) {\n\t\t// Console.log( \"tree\", tree.value );\n\t\t// console.log( \"parent\", parent.value );\n\n\t\t// Here, we cannot just swap values as it would invalidate\n\t\t// externally stored references.\n\t\t// Instead, we swap children lists and update references\n\t\t// between the tree and its parent.\n\t\t// Then we update and return the new tree's parent.\n\n\t\t// console.log( \"tree.children\", tree.children );\n\t\t// console.log( \"parent.children\", parent.children );\n\n\t\tconst tmp = parent.children;\n\t\tparent.children = tree.children;\n\t\ttree.children = tmp;\n\n\t\tconst i = parent.rank();\n\n\t\t// Console.log( tree.children, i );\n\n\t\ttree.children[i] = parent;\n\n\t\ttree.parent = parent.parent;\n\n\t\tchange_parent(tree, tree.children);\n\t\tchange_parent(parent, parent.children);\n\n\t\t// Console.log( \"tree.children\", tree.children );\n\t\t// console.log( \"parent.children\", parent.children );\n\n\t\treturn tree.parent;\n\t};\n\n\tconst percolate_up = function (list, tree) {\n\t\tlet parent = tree.parent;\n\n\t\tif (parent !== null) {\n\t\t\twhile (true) {\n\t\t\t\tparent = shift_up(tree, parent);\n\n\t\t\t\tif (parent === null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// TODO this call might not be necessary\n\t\t\t\tparent.children[tree.rank()] = tree;\n\t\t\t}\n\n\t\t\tlist[tree.rank()] = tree;\n\t\t}\n\t};\n\n\tconst decreasekey = function (compare, list, tree, value) {\n\t\ttree.value = value;\n\t\tlet parent = tree.parent;\n\n\t\tif (parent !== null) {\n\t\t\twhile (true) {\n\t\t\t\tconst d = compare(value, parent.value);\n\n\t\t\t\tif (d >= 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tparent = shift_up(tree, parent);\n\n\t\t\t\tif (parent === null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// TODO this call should be in if ( d >= 0 )\n\t\t\t\tparent.children[tree.rank()] = tree;\n\t\t\t}\n\n\t\t\tlist[tree.rank()] = tree;\n\t\t}\n\t};\n\n\tconst deletetree = function (compare, list, tree) {\n\t\tpercolate_up(list, tree);\n\n\t\tremove_head_at_index(compare, list, tree.rank(), list.length);\n\n\t\ttree.detach();\n\t};\n\n\tconst Heap = function (compare) {\n\t\t// The compare function to use to compare values\n\n\t\tthis.compare = compare;\n\n\t\t// Number of elements in this heap\n\n\t\tthis.length = 0;\n\n\t\t// List of binomial trees\n\n\t\tthis.list = [];\n\t};\n\n\tHeap.prototype.head = function () {\n\t\tif (this.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst i = find_min_index(this.compare, this.list, 0, this.list.length);\n\n\t\tconst tree = this.list[i];\n\n\t\treturn tree.value;\n\t};\n\n\tHeap.prototype.headreference = function () {\n\t\tif (this.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst i = find_min_index(this.compare, this.list, 0, this.list.length);\n\n\t\tconst tree = this.list[i];\n\n\t\treturn tree;\n\t};\n\n\tHeap.prototype.pop = function () {\n\t\tif (this.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t--this.length;\n\n\t\treturn binomial_heap_pop(this.compare, this.list).value;\n\t};\n\n\tHeap.prototype.popreference = function () {\n\t\tif (this.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t--this.length;\n\n\t\treturn binomial_heap_pop(this.compare, this.list).detach();\n\t};\n\n\tHeap.prototype.push = function (value) {\n\t\t// Push a new tree of rank 0\n\n\t\tconst tree = new BinomialTree(value, []);\n\n\t\tthis.pushreference(tree);\n\n\t\treturn tree;\n\t};\n\n\tHeap.prototype.pushreference = function (tree) {\n\t\t++this.length;\n\n\t\t// Push an existing tree of rank 0\n\n\t\tbinomial_heap_push(this.compare, this.list, tree, 0);\n\t};\n\n\tHeap.prototype.merge = function (other) {\n\t\tmerge(this.compare, this.list, other.list);\n\n\t\tthis.length += other.length;\n\n\t\treturn this;\n\t};\n\n\tHeap.prototype.update = function (tree, value) {\n\t\tconst d = this.compare(value, tree.value);\n\n\t\tif (d < 0) {\n\t\t\tthis.decreasekey(tree, value);\n\t\t} else if (d > 0) {\n\t\t\tthis.increasekey(tree, value);\n\t\t} else {\n\t\t\t// D === 0 does not imply tree.value === value\n\n\t\t\ttree.value = value;\n\t\t}\n\t};\n\n\tHeap.prototype.decreasekey = function (tree, value) {\n\t\tdecreasekey(this.compare, this.list, tree, value);\n\t};\n\n\tHeap.prototype.increasekey = function (tree, value) {\n\t\tdeletetree(this.compare, this.list, tree);\n\n\t\ttree.value = value;\n\n\t\tbinomial_heap_push(this.compare, this.list, tree, 0);\n\t};\n\n\tHeap.prototype.delete = function (tree) {\n\t\t--this.length;\n\n\t\tdeletetree(this.compare, this.list, tree);\n\t};\n\n\treturn Heap;\n}\n","import LazyStack from './LazyStack.js';\n\nexport default function LazyBinomialHeap(BinomialTree) {\n\tconst lazy_binomial_heap_push = function (lazy, tree, rank) {\n\t\t// Lightweight binomial heap containing a unique tree\n\t\tconst sequence = [];\n\n\t\t// Offset tree by its rank\n\t\tlet i = rank;\n\n\t\twhile (i--) {\n\t\t\tsequence.push(null);\n\t\t}\n\n\t\tsequence.push(tree);\n\n\t\t// Do not merge the generated sequence immediately\n\t\tlazy.push(sequence);\n\t};\n\n\tconst merge = function (compare, list, other) {\n\t\tif (other.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Merging two binomial heaps is like\n\t\t// adding two little endian integers\n\t\t// so, we first make sure that we have\n\t\t// enough place to store the result\n\n\t\tlet i = other.length - list.length;\n\n\t\twhile (i-- > 0) {\n\t\t\tlist.push(null);\n\t\t}\n\n\t\tlet carry = null;\n\n\t\tconst len = list.length;\n\n\t\t// Remember len >= other.length\n\n\t\tfor (i = 0; i < len; ++i) {\n\t\t\t// Other[i] can be either null or not\n\t\t\t// list[i] can be either null or not\n\t\t\t// carry can be either null or not\n\t\t\t// --> 2^3 = 8 possibilities\n\t\t\t//\n\t\t\t// null ? | other[i] | list[i] | carry\n\t\t\t// ---------------------------------------\n\t\t\t// (0) | no | no | no\n\t\t\t// (1) | no | no | yes\n\t\t\t// (2) | no | yes | no\n\t\t\t// (3) | no | yes | yes\n\t\t\t// (4) | yes | no | no\n\t\t\t// (5) | yes | no | yes\n\t\t\t// (6) | yes | yes | no\n\t\t\t// (7) | yes | yes | yes\n\n\t\t\tif (i >= other.length || other[i] === null) {\n\t\t\t\tif (carry !== null) {\n\t\t\t\t\t// (6) other[i] = null and list[i] = null and carry != null\n\t\t\t\t\t// --> put carry in current cell\n\n\t\t\t\t\tif (list[i] === null) {\n\t\t\t\t\t\tlist[i] = carry;\n\t\t\t\t\t\tcarry = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// (4) other[i] = null and list[i] != null and carry != null\n\t\t\t\t\t// --> merge carry with current cell\n\t\t\t\t\telse {\n\t\t\t\t\t\tcarry = carry.merge(compare, list[i]);\n\t\t\t\t\t\tlist[i] = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// We do not need to do anything for\n\t\t\t\t// those 2 cases (carry and other[i] are null).\n\t\t\t\t// ==\n\t\t\t\t// (5) other[i] = null and list[i] != null and carry = null\n\t\t\t\t// (7) other[i] = null and list[i] = null and carry = null\n\t\t\t}\n\n\t\t\t// (0) other[i] != null and list[i] != null and carry != null\n\t\t\t// (2) other[i] != null and list[i] = null and carry != null\n\t\t\t// --> merge carry with other[i]\n\t\t\telse if (carry !== null) {\n\t\t\t\tcarry = carry.merge(compare, other[i]);\n\t\t\t}\n\n\t\t\t// (1) other[i] != null and list[i] != null and carry = null\n\t\t\t// --> merge current cell with other[i]\n\t\t\telse if (list[i] !== null) {\n\t\t\t\tcarry = list[i].merge(compare, other[i]);\n\t\t\t\tlist[i] = null;\n\t\t\t}\n\n\t\t\t// (3) other[i] != null and list[i] = null and carry = null\n\t\t\t// --> put other[i] in list\n\t\t\telse {\n\t\t\t\tlist[i] = other[i];\n\t\t\t}\n\t\t}\n\n\t\t// Do not forget to append last carry\n\n\t\tif (carry !== null) {\n\t\t\tlist.push(carry);\n\t\t}\n\t};\n\n\tconst lazy_binomial_heap_pop = function (compare, list, lazy) {\n\t\t// Amortized merge of stored values\n\n\t\twhile (!lazy.empty()) merge(compare, list, lazy.pop());\n\n\t\t// Standard O(log n) optimum search method\n\n\t\tconst len = list.length;\n\n\t\t// There MUST be at least one\n\t\t// non null element in this list\n\t\t// we look for the first one\n\n\t\tlet j = 0;\n\t\tfor (; j < len - 1 && list[j] === null; ++j);\n\n\t\t// Here j is necessarily < len\n\t\t// and list[j] is non null\n\n\t\tlet i = j;\n\t\tlet opt = list[j].value;\n\n\t\t// We lookup remaining elements to see if there\n\t\t// is not a better candidate\n\n\t\tfor (++j; j < len; ++j) {\n\t\t\tconst item = list[j];\n\n\t\t\tif (item !== null) {\n\t\t\t\tconst candidate = item.value;\n\n\t\t\t\tif (compare(candidate, opt) < 0) {\n\t\t\t\t\ti = j;\n\t\t\t\t\topt = candidate;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst orphan = list[i].children;\n\t\tlist[i] = null;\n\n\t\t// We just removed the ith element\n\t\t// if list[i] is the last cell\n\t\t// of list we can drop it\n\n\t\tif (i === len - 1) {\n\t\t\tlist.pop();\n\t\t}\n\n\t\t// We store the children in the\n\t\t// lazy list\n\n\t\tlazy.push(orphan);\n\n\t\treturn opt;\n\t};\n\n\tconst Heap = function (compare) {\n\t\t// The compare function to use to compare values\n\n\t\tthis.compare = compare;\n\n\t\t// Number of elements in this heap\n\n\t\tthis.length = 0;\n\n\t\t// List of binomial trees\n\n\t\tthis.list = [];\n\n\t\t// List of binomial heaps waiting to be merged\n\n\t\tthis.lazy = new LazyStack();\n\t};\n\n\tHeap.prototype.pop = function () {\n\t\tif (this.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t--this.length;\n\n\t\treturn lazy_binomial_heap_pop(this.compare, this.list, this.lazy);\n\t};\n\n\tHeap.prototype.push = function (value) {\n\t\t++this.length;\n\n\t\t// Push a new tree of rank 0\n\n\t\treturn lazy_binomial_heap_push(this.lazy, new BinomialTree(value, []), 0);\n\t};\n\n\tHeap.prototype.merge = function (other) {\n\t\tthis.lazy.meld(other.lazy);\n\n\t\tthis.length += other.length;\n\n\t\treturn this;\n\t};\n\n\treturn Heap;\n}\n"],"names":["BinomialTree","value","children","this","BinomialTreeWithParent","parent","LazyNode","next","LazyStack","top","bottom","prototype","merge","predicate","other","concat","detach","splice","setparent","_parent","rank","length","empty","push","pop","meld","binomial_heap_push","compare","list","tree","i","len","carry","find_min_index","j","opt","item","candidate","remove_head_at_index","orphans","change_parent","binomial_heap_pop","shift_up","tmp","deletetree","percolate_up","Heap","head","headreference","popreference","pushreference","update","d","decreasekey","increasekey","delete","lazy","orphan","lazy_binomial_heap_pop","sequence","lazy_binomial_heap_push"],"mappings":"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"}