From 0652e7eb43caa2f229e3c2f450c29c261f8dbe42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20P=C3=B3=C5=82grabia?= Date: Mon, 7 Mar 2022 22:54:50 +0100 Subject: [PATCH] Adding binomial heap implementation. --- 2022/03/algorithms/fibonacci_heap.js | 153 +++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 2022/03/algorithms/fibonacci_heap.js diff --git a/2022/03/algorithms/fibonacci_heap.js b/2022/03/algorithms/fibonacci_heap.js new file mode 100644 index 0000000..d039822 --- /dev/null +++ b/2022/03/algorithms/fibonacci_heap.js @@ -0,0 +1,153 @@ +"use strict"; + +// const fs = require('fs'); +// const {EOL} = require('os'); + +function log(s) { + // console.log(s); +} + +function find_min(l) { + if (!l || !l.length) { + return null; + } + + let min = l[0]; + let idx = 0; + for (let i = 1; i < l.length; i++) { + if (min.value > l[i].value) { + min = l[i]; + idx = i; + } + } + + return [min, idx]; +} + +function merge_some_level_trees(l, r) { + // merge it into level+1 and it becomes t + if (l.value < r.value) { + // l becomes root + l.children.push(r); + l.level++; + return l; + } else { + // r becomes root + r.children.push(l); + r.level++; + return r; + } + +} + +function heap_insert(nodes, el) { + log('Heap insert nodes: ', nodes, ', element: ', el); + return merge_tree_lists(nodes, [{ + value: el, + level: 0, + children: [] + }]); +} + +function merge_tree_lists(l, r) { + log('Merging tree lists l: ', l, ', r: ', r); + if (!l) { + return r; + } + + if (!r) { + return l; + } + + let x = []; + + // assuming both l and r are correct fibonacci heaps so max 2 trees with the same level + let idx = 0; + while (l.length && r.length) { + log(`${idx}. loop iteration`); + if (l[0].level < r[0].level) { + log('Case 1 l level is smaller than r level. Adding l[0]'); + x.push(l.shift()); + } else if (l[0].level > r[0].level) { + log('Case 2 l level is bigger than r level. Adding r[0]'); + x.push(r.shift()); + } else { + // l[0].level === r[0].level + log('Case 3 l is the same as r level. Adding both'); + x.push(l.shift()); + x.push(r.shift()); + } + ++idx; + } + log(`End of loop after ${idx} iterations`); + log('l: ', l, ', r: ', r); + if (l.length) { + x = x.concat(l); + } else if (r.length) { + x = x.concat(r); + } + + log('x: ', x); + + // the situation is we have sorted by level (ascending) with max 2 neighbouring + // trees with the same level + + let res = []; + let t1, t2, t; + while (x.length > 1) { + if (x[0].level < x[1].level) { + res.push(x.shift()); + } else { + // with the same level + t1 = x.shift(); + t2 = x.shift(); + x.unshift(merge_some_level_trees(t1, t2)); + } + } + + // case 0 or 1 + + while (x.length) { + res.push(x.shift()); + } + + return res; +} + +function delete_heap_min(nodes) { + log(`Delete heap min l ${nodes.length}`); + let [node, idx] = find_min(nodes); + nodes.splice(idx, 1); + return merge_tree_lists(nodes, node.children); +} + +let heap = []; +// heap = heap_insert(heap, -2); +heap = heap_insert(heap, 2); +// heap = heap_insert(heap, -3); +heap = heap_insert(heap, 3); +// heap = heap_insert(heap, -1); +heap = heap_insert(heap, -10); +// heap = heap_insert(heap, 20); +heap = heap_insert(heap, 100); + +heap = heap_insert(heap, 3); +heap = heap_insert(heap, 2); +heap = heap_insert(heap, 1); +heap = heap_insert(heap, -100); +heap = heap_insert(heap, -1); +heap = heap_insert(heap, -4); +heap = heap_insert(heap, 4); +heap = heap_insert(heap, 5); +heap = heap_insert(heap, 6); + +console.log(`Forrest of binomial trees ${heap.length}`); +for (let el of heap) { + console.log(`${el.value} ${el.level}`); +} + +while (heap.length) { + let [node, idx] = find_min(heap); + console.log(`Node ${node.value}, idx: ${idx}`); + heap = delete_heap_min(heap); +}