Adding binomial heap implementation.

master
Tomasz Półgrabia 2022-03-07 22:54:50 +01:00
parent 51aa461729
commit 0652e7eb43
1 changed files with 153 additions and 0 deletions

View File

@ -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);
}