feat: Add comments to currently run operations

Fixes #8

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2022-05-15 17:53:12 +02:00
parent 23a0653d23
commit c7c27300f6
Signed by: mfocko
GPG key ID: 7C47D46246790496
7 changed files with 79 additions and 39 deletions

30
avl.js
View file

@ -41,28 +41,32 @@ class AVLTree extends RankedTree {
if (rotatingAroundRoot) {
this.root = newRoot;
}
this.record();
this.record("Fixing 0-child by single rotation: by z");
z.demote();
this.record();
this.record("Fixing 0-child by single rotation: demoting z");
} else if (nodeDifference(y) == 1) {
rotateLeft(x);
this.record();
this.record(
"Fixing 0-child by double-rotation: first rotation by x"
);
newRoot = rotateRight(z);
if (rotatingAroundRoot) {
this.root = newRoot;
}
this.record();
this.record(
"Fixing 0-child by double-rotation: second rotation by z"
);
y.promote();
this.record();
this.record("Fixing 0-child by double-rotation: promoting y");
x.demote();
this.record();
this.record("Fixing 0-child by double-rotation: demoting x");
z.demote();
this.record();
this.record("Fixing 0-child by double-rotation: demoting z");
}
}
@ -72,7 +76,7 @@ class AVLTree extends RankedTree {
x.parent.promote();
x = x.parent;
this.record();
this.record("Insertion rebalance: promoting (0, 1) parent");
diffs = nodeDifferences(x.parent).sort();
}
@ -122,7 +126,7 @@ class AVLTree extends RankedTree {
break;
default:
rotateRight(y);
this.record();
this.record("AVL deletion, fixing by double-rotation: by y");
newRoot = rotateLeft(x);
break;
@ -130,13 +134,13 @@ class AVLTree extends RankedTree {
if (rotatingAroundRoot) {
this.root = newRoot;
}
this.record();
this.record("AVL deletion, fixing by rotation by x");
[newRoot.left, newRoot.right, newRoot]
.filter((x) => x)
.forEach((n) => {
updateRank(n);
this.record();
this.record("Updating rank of nodes affected by rotations");
});
return factor == 0;
@ -149,7 +153,9 @@ class AVLTree extends RankedTree {
switch (factor) {
case 0:
updateRank(x);
this.record();
this.record(
"Updating rank of node affected by the propagation of delete"
);
return false;
case -1:

View file

@ -1,9 +1,11 @@
let lRecorder = new Recorder(
d3.select("#left").graphviz(),
null,
"left"
).renderAtOnce();
let rRecorder = new Recorder(
d3.select("#right").graphviz(),
null,
"right"
).renderAtOnce();

View file

@ -32,6 +32,7 @@
<input type="submit" value="Delete" />
</form>
<p>Current operation: <span id="comment"></span></p>
<div id="graph" style="text-align: center"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>

View file

@ -68,11 +68,11 @@ class RankedTree {
return this.toDot().join("\n");
}
record() {
record(message) {
if (!this.recorder) {
return;
}
this.recorder.record(this);
this.recorder.record(this, message);
}
rank() {
@ -92,7 +92,7 @@ class RankedTree {
if (!this.root) {
this.root = insertedNode;
this.record();
this.record("Inserting key to the root");
return;
}
@ -108,7 +108,7 @@ class RankedTree {
} else {
parent.right = insertedNode;
}
this.record();
this.record("Inserting key");
this.insertRebalance(insertedNode);
}
@ -146,12 +146,14 @@ class RankedTree {
node.value = successor.value;
successor.value = null;
this.record();
this.record(
"Replacing the value of deleted node with successor value"
);
return this.deleteNode(successor);
}
this.record();
this.record("Replacing the node with one of its children");
return [y, parent];
}

View file

@ -1,8 +1,23 @@
const DURATION = 500;
class Record {
constructor(tree, message) {
this.tree = tree;
this.message = message;
}
render(graph, textBox) {
graph.renderDot(this.tree);
if (textBox) {
textBox.textContent = this.message;
}
}
}
class Recorder {
constructor(graph, id) {
constructor(graph, textBox, id) {
this.graph = graph;
this.textBox = textBox;
this.id = id;
this.rendered = -1;
@ -20,8 +35,6 @@ class Recorder {
}
unblockRendering() {
console.log(this);
console.log(`Unblocked renderer #${this.id}`);
this.rendering = false;
}
@ -40,7 +53,7 @@ class Recorder {
if (this.atOnce) {
if (this.rendered != this.states.length - 1) {
this.rendered = this.states.length - 1;
this.graph.renderDot(this.states[this.rendered]);
this.states[this.rendered].render(this.graph, this.textBox);
}
return;
@ -57,7 +70,7 @@ class Recorder {
this.rendering = true;
this.rendered++;
this.graph.renderDot(this.states[this.rendered]);
this.states[this.rendered].render(this.graph, this.textBox);
}
previous() {
@ -68,9 +81,9 @@ class Recorder {
throw "not implemented!";
}
record(tree) {
record(tree, message) {
// TODO: adjust join if necessary
this.states.push(tree.toDot().join(""));
this.states.push(new Record(tree.toDot().join(""), message));
this.render();
}
}

View file

@ -1,4 +1,8 @@
let recorder = new Recorder(d3.select("#graph").graphviz(), "graph");
let recorder = new Recorder(
d3.select("#graph").graphviz(),
document.getElementById("comment"),
"graph"
);
let tree = new WAVLTree();
tree.recorder = recorder;

38
wavl.js
View file

@ -36,36 +36,48 @@ class WAVLTree extends AVLTree {
if (rotatingAroundRoot) {
this.root = newRoot;
}
this.record();
this.record(
"Final step of deletion rebalance: single rotation by parent of y"
);
y.promote();
this.record();
this.record("Final step of deletion rebalance: promotion of y");
z.demote();
this.record();
this.record("Final step of deletion rebalance: demotion of z");
if (z.type() == LEAF) {
z.demote();
this.record();
this.record(
"Final step of deletion rebalance: demotion of leaf z"
);
}
} else if (wDiff == 2 && v && v.parent) {
rotateRight(v.parent);
this.record();
this.record(
"Final step of deletion rebalance: first of double rotation by parent of v"
);
newRoot = rotateLeft(v.parent);
if (rotatingAroundRoot) {
this.root = newRoot;
}
this.record();
this.record(
"Final step of deletion rebalance: second of double rotation by parent of v"
);
v.promote().promote();
this.record();
this.record(
"Final step of deletion rebalance: double promotion of v"
);
y.demote();
this.record();
this.record("Final step of deletion rebalance: demotion of y");
z.demote().demote();
this.record();
this.record(
"Final step of deletion rebalance: double demotion of z"
);
}
}
@ -85,11 +97,11 @@ class WAVLTree extends AVLTree {
(yDiff == 2 || nodeDifferences(y).equals([2, 2]))
) {
parent.demote();
this.record();
this.record("Propagating error by demoting parent");
if (yDiff != 2) {
y.demote();
this.record();
this.record("Demoting y");
}
x = parent;
@ -139,12 +151,12 @@ class WAVLTree extends AVLTree {
deleteFixup(y, parent) {
if (nodeDifferences(y).equals([2, 2])) {
y.demote();
this.record();
this.record("Starting deletion rebalance by demoting (2, 2) node");
parent = y.parent;
} else if (nodeDifferences(parent).equals([2, 2])) {
parent.demote();
this.record();
this.record("Starting deletion rebalance by demoting (2, 2) node");
parent = parent.parent;
}