fix: Ensure all affected nodes are being highlighted

Fixes #9

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2022-05-16 18:36:31 +02:00
parent 030cd9a701
commit 43ade1120b
Signed by: mfocko
GPG key ID: 7C47D46246790496
5 changed files with 34 additions and 20 deletions

20
avl.js
View file

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

View file

@ -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() {

View file

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

View file

@ -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
View file

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