web/wavl.js
Matej Focko f5c746b783
feat: port python code to JS
Signed-off-by: Matej Focko <mfocko@redhat.com>
2022-04-27 21:37:58 +02:00

123 lines
No EOL
3.1 KiB
JavaScript

class WAVLTree extends AVLTree {
isCorrectNode(node, recursive) {
if (!node) {
return true;
}
nodeDifferences(node).forEach(childRank => {
if ([1, 2].findIndex(childRank) == -1) {
return false;
}
});
if (node.type() == LEAF) {
return node.rank == 0;
}
return !(recursive ?? true) || (this.isCorrectNode(node.left) && this.isCorrectNode(node.right));
}
fixDelete(x, y, z, reversed, rotateLeft, rotateRight) {
let newRoot = x;
let [v, w] = [y.left, y.right];
if (reversed) {
[v, w] = [w, v];
}
let wDiff = nodeDifference(w, y);
if (wDiff == 1 && y.parent) {
newRoot = rotateLeft(y.parent);
y.promote();
z.demote();
if (z.type() == LEAF) {
z.demote();
}
} else if (wDiff == 2 && v && v.parent) {
rotateRight(v.parent);
newRoot = rotateLeft(v.parent);
v.promote().promote();
y.demote();
z.demote().demote();
}
return newRoot;
}
bottomUpDelete(x, parent) {
let xDiff = nodeDifference(x, parent);
if (xDiff != 3 || !parent) {
return;
}
let y = (parent.left === x) ? parent.right : parent.left;
let yDiff = nodeDifference(y, parent);
while (parent && xDiff == 3 && y && (yDiff == 2 || nodeDifferences(y).equals([2, 2]))) {
parent.demote();
if (yDiff != 2) {
y.demote();
}
x = parent;
parent = x.parent;
if (!parent) {
return;
}
let y = (parent.left === x) ? parent.right : parent.left;
xDiff = nodeDifference(x, parent);
yDiff = nodeDifference(y, parent);
}
if (!parent) {
return;
}
let rotatingAroundRoot = parent.parent == null;
let newRoot = parent;
let parentNodeDiffs = nodeDifferences(parent);
if (parentNodeDiffs.sort().equals([1, 3])) {
if (parent.left === x) {
newRoot = this.fixDelete(x, parent.right, parent, false, rotateLeft, rotateRight);
} else {
newRoot = this.fixDelete(x, parent.left, parent, true, rotateRight, rotateLeft);
}
}
if (rotatingAroundRoot) {
this.root = newRoot;
}
}
deleteFixup(y, parent) {
let z = (y) ? y : parent;
if (nodeDifferences(z).equals([2, 2])) {
z.demote();
}
if (!parent) {
return;
}
[parent.left, parent.right].forEach(y => {
if (nodeDifference(y, parent) == 3) {
this.bottomUpDelete(y, parent);
}
});
}
deleteRebalance(node, parent) {
while (node || parent) {
this.deleteFixup(node, parent);
[node, parent] = parent, (parent) ? parent.parent : null;
}
}
}