fix: Ensure all affected nodes are being highlighted
Fixes #9 Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
030cd9a701
commit
43ade1120b
5 changed files with 34 additions and 20 deletions
20
avl.js
20
avl.js
|
@ -41,15 +41,16 @@ class AVLTree extends RankedTree {
|
||||||
if (rotatingAroundRoot) {
|
if (rotatingAroundRoot) {
|
||||||
this.root = newRoot;
|
this.root = newRoot;
|
||||||
}
|
}
|
||||||
this.record("Fixing 0-child by single rotation: by z", z);
|
this.record("Fixing 0-child by single rotation: by z", z, newRoot);
|
||||||
|
|
||||||
z.demote();
|
z.demote();
|
||||||
this.record("Fixing 0-child by single rotation: demoting z", z);
|
this.record("Fixing 0-child by single rotation: demoting z", z);
|
||||||
} else if (nodeDifference(y) == 1) {
|
} else if (nodeDifference(y) == 1) {
|
||||||
rotateLeft(x);
|
let intermediateRoot = rotateLeft(x);
|
||||||
this.record(
|
this.record(
|
||||||
"Fixing 0-child by double-rotation: first rotation by x",
|
"Fixing 0-child by double-rotation: first rotation by x",
|
||||||
x
|
x,
|
||||||
|
intermediateRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
newRoot = rotateRight(z);
|
newRoot = rotateRight(z);
|
||||||
|
@ -58,7 +59,8 @@ class AVLTree extends RankedTree {
|
||||||
}
|
}
|
||||||
this.record(
|
this.record(
|
||||||
"Fixing 0-child by double-rotation: second rotation by z",
|
"Fixing 0-child by double-rotation: second rotation by z",
|
||||||
z
|
z,
|
||||||
|
newRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
y.promote();
|
y.promote();
|
||||||
|
@ -129,8 +131,12 @@ class AVLTree extends RankedTree {
|
||||||
newRoot = rotateLeft(x);
|
newRoot = rotateLeft(x);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rotateRight(y);
|
let intermediateRoot = rotateRight(y);
|
||||||
this.record("AVL deletion, fixing by double-rotation: by y", y);
|
this.record(
|
||||||
|
"AVL deletion, fixing by double-rotation: by y",
|
||||||
|
y,
|
||||||
|
intermediateRoot
|
||||||
|
);
|
||||||
|
|
||||||
newRoot = rotateLeft(x);
|
newRoot = rotateLeft(x);
|
||||||
break;
|
break;
|
||||||
|
@ -138,7 +144,7 @@ class AVLTree extends RankedTree {
|
||||||
if (rotatingAroundRoot) {
|
if (rotatingAroundRoot) {
|
||||||
this.root = newRoot;
|
this.root = newRoot;
|
||||||
}
|
}
|
||||||
this.record("AVL deletion, fixing by rotation by x", x);
|
this.record("AVL deletion, fixing by rotation by x", x, newRoot);
|
||||||
|
|
||||||
[newRoot.left, newRoot.right, newRoot]
|
[newRoot.left, newRoot.right, newRoot]
|
||||||
.filter((x) => x)
|
.filter((x) => x)
|
||||||
|
|
|
@ -4,7 +4,7 @@ class RankedTree {
|
||||||
this.recorder = null;
|
this.recorder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getUnwrappedGraph(highlightedNode) {
|
_getUnwrappedGraph(...highlightedNodes) {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
let q = new Queue();
|
let q = new Queue();
|
||||||
|
@ -18,8 +18,9 @@ class RankedTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
let [value, rank] = [node.value, node.rank];
|
let [value, rank] = [node.value, node.rank];
|
||||||
let highlight =
|
let highlight = highlightedNodes.includes(node)
|
||||||
node === highlightedNode ? ', color="blue", penwidth=3' : "";
|
? ', color="blue", penwidth=3'
|
||||||
|
: "";
|
||||||
result.push(
|
result.push(
|
||||||
`\t"Node(${value})" [label="${value}, ${rank}"${highlight}];\n`
|
`\t"Node(${value})" [label="${value}, ${rank}"${highlight}];\n`
|
||||||
);
|
);
|
||||||
|
@ -46,10 +47,10 @@ class RankedTree {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
toDot(highlightedNode) {
|
toDot(...highlightedNodes) {
|
||||||
return [
|
return [
|
||||||
"digraph {\n",
|
"digraph {\n",
|
||||||
...this._getUnwrappedGraph(highlightedNode),
|
...this._getUnwrappedGraph(...highlightedNodes),
|
||||||
"}\n",
|
"}\n",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -58,11 +59,11 @@ class RankedTree {
|
||||||
return this.toDot().join("\n");
|
return this.toDot().join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
record(message, highlightedNode) {
|
record(message, ...highlightedNodes) {
|
||||||
if (!this.recorder) {
|
if (!this.recorder) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.recorder.record(this, message, highlightedNode);
|
this.recorder.record(this, message, ...highlightedNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
rank() {
|
rank() {
|
||||||
|
|
1
ravl.js
1
ravl.js
|
@ -16,6 +16,7 @@ class RAVLTree extends WAVLTree {
|
||||||
|
|
||||||
deleteRebalance(node, parent) {
|
deleteRebalance(node, parent) {
|
||||||
// no-op
|
// no-op
|
||||||
|
this.record("No rebalancing occurs");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,10 +84,10 @@ class Recorder {
|
||||||
throw "not implemented!";
|
throw "not implemented!";
|
||||||
}
|
}
|
||||||
|
|
||||||
record(tree, message, highlightedNode) {
|
record(tree, message, ...highlightedNodes) {
|
||||||
// TODO: adjust join if necessary
|
// TODO: adjust join if necessary
|
||||||
this.states.push(
|
this.states.push(
|
||||||
new Record(tree.toDot(highlightedNode).join(""), message)
|
new Record(tree.toDot(...highlightedNodes).join(""), message)
|
||||||
);
|
);
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
14
wavl.js
14
wavl.js
|
@ -32,13 +32,15 @@ class WAVLTree extends AVLTree {
|
||||||
let wDiff = nodeDifference(w, y);
|
let wDiff = nodeDifference(w, y);
|
||||||
|
|
||||||
if (wDiff == 1 && y.parent) {
|
if (wDiff == 1 && y.parent) {
|
||||||
|
let oldRoot = y.parent;
|
||||||
newRoot = rotateLeft(y.parent);
|
newRoot = rotateLeft(y.parent);
|
||||||
if (rotatingAroundRoot) {
|
if (rotatingAroundRoot) {
|
||||||
this.root = newRoot;
|
this.root = newRoot;
|
||||||
}
|
}
|
||||||
this.record(
|
this.record(
|
||||||
"Final step of deletion rebalance: single rotation by parent of y",
|
"Final step of deletion rebalance: single rotation by parent of y",
|
||||||
y.parent
|
oldRoot,
|
||||||
|
newRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
y.promote();
|
y.promote();
|
||||||
|
@ -55,19 +57,23 @@ class WAVLTree extends AVLTree {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (wDiff == 2 && v && v.parent) {
|
} else if (wDiff == 2 && v && v.parent) {
|
||||||
rotateRight(v.parent);
|
let oldRoot = v.parent;
|
||||||
|
let intermediateRoot = rotateRight(v.parent);
|
||||||
this.record(
|
this.record(
|
||||||
"Final step of deletion rebalance: first of double rotation by parent of v",
|
"Final step of deletion rebalance: first of double rotation by parent of v",
|
||||||
v.parent
|
oldRoot,
|
||||||
|
intermediateRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
|
oldRoot = v.parent;
|
||||||
newRoot = rotateLeft(v.parent);
|
newRoot = rotateLeft(v.parent);
|
||||||
if (rotatingAroundRoot) {
|
if (rotatingAroundRoot) {
|
||||||
this.root = newRoot;
|
this.root = newRoot;
|
||||||
}
|
}
|
||||||
this.record(
|
this.record(
|
||||||
"Final step of deletion rebalance: second of double rotation by parent of v",
|
"Final step of deletion rebalance: second of double rotation by parent of v",
|
||||||
v.parent
|
oldRoot,
|
||||||
|
newRoot
|
||||||
);
|
);
|
||||||
|
|
||||||
v.promote().promote();
|
v.promote().promote();
|
||||||
|
|
Loading…
Reference in a new issue