Skip to content

Commit 55cb5a2

Browse files
committed
Broken?? AVL rotation node positions
1 parent 15985a2 commit 55cb5a2

File tree

5 files changed

+97
-52
lines changed

5 files changed

+97
-52
lines changed

package-lock.json

Lines changed: 22 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/algorithms/controllers/AVLTreeInsertion.js

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,44 @@ export default {
6060
}
6161
}
6262

63+
/**
64+
* compute node positions during rotation
65+
* given x-y coordinates of the root and the child, compute the
66+
* intermediate position after step 1 or step 2
67+
* coords represented as record with fields rX, rY, cX, cY (root X&Y,
68+
* child X&Y)
69+
* We keep the edge the same length and rotate it around the point 40%
70+
* along the edge from the root. If initially the y coordinate of the
71+
* root is 1 and the child is zero, after step 1 the root is at 2/3
72+
* and the child is at 1/2 and after step 2 the root is at 1/3 and the
73+
* child is at 1. The x coordinates are computed so as to keep the length
74+
* of the edge same (magic numbers derived from maths).
75+
* returns record with new coordinates
76+
*/
77+
function rotateStep(pos0, step) {
78+
79+
let {rX, rY, cX, cY} = pos0;
80+
let deltaX = rX - cX;
81+
let deltaY = rY - cY;
82+
// edge length = sqrt(deltaX**2 + deltaY**2)
83+
let deltaX1; // deltaX for new position
84+
let pos1 = {rX:0, rY:0, cX:0, cY:0};
85+
if (step == 1) {
86+
pos1.rY = (2*rY + cY) / 3;
87+
pos1.cY = (rY + cY) / 2;
88+
deltaX1 = Math.sqrt((35/36)*deltaY**2 + deltaX**2);
89+
} else { // assume step == 2
90+
pos1.rY = (rY + 2*cY) / 3;
91+
pos1.cY = rY;
92+
deltaX1 = Math.sqrt((5/9)*deltaY**2 + deltaX**2);
93+
}
94+
if (rX > cX) // reverse direction of deltaX
95+
deltaX1 = -deltaX1;
96+
pos1.rX = (0.6*rX + 0.4*cX) - 0.4*deltaX1;
97+
pos1.cX = (0.6*rX + 0.4*cX) + 0.6*deltaX1;
98+
return pos1;
99+
}
100+
63101
// We apply the following char notations in our rotation code.
64102
// It helps code reusability and readability.
65103
// tNum / charNotation
@@ -116,17 +154,11 @@ export default {
116154
let rootNode = vis.graph.findNode(tt6);
117155
let leafNode = vis.graph.findNode(tt2);
118156
// store the previous height of the root node
119-
vis.graph.storePrevHeight(rootNode.y);
120-
// calculate the new position of the nodes
121-
let newY = (rootNode.y + leafNode.y) / 2;
122-
let moveX = 0;
123-
// avoid overlapping
124-
if ((rootNode.x - leafNode.x) < nodeSize) {
125-
moveX = nodeSize - (rootNode.x - leafNode.x);
126-
}
127-
// set the new position of the nodes
128-
vis.graph.setNodePosition(tt6, rootNode.x + moveX, newY);
129-
vis.graph.setNodePosition(tt2, leafNode.x - moveX, newY);
157+
let pos0 = {rX:rootNode.x, rY:rootNode.y, cX:leafNode.x, cY:leafNode.y};
158+
vis.graph.setRotPos(pos0);
159+
let pos = rotateStep(pos0, 1); // compute new position
160+
vis.graph.setNodePosition(tt6, pos.rX, pos.rY);
161+
vis.graph.setNodePosition(tt2, pos.cX, pos.cY);
130162
},
131163
[A.key, R.key],
132164
depth
@@ -144,14 +176,14 @@ export default {
144176
}
145177

146178
// -- following code is for visualising the rotation step by step --
147-
let rootNode = vis.graph.findNode(tt6);
179+
let rootNode = vis.graph.findNode(tt2);
148180
let leafNode = vis.graph.findNode(tt2);
149181
// freeze the layout to avoid the nodes moving automatically
150182
vis.graph.setPauseLayout(true);
151-
let move = (rootNode.x - leafNode.x) / 5;
152-
// set the new position of the nodes
153-
vis.graph.setNodePosition(tt2, leafNode.x + move, vis.graph.getPrevHeight());
154-
vis.graph.setNodePosition(tt6, rootNode.x - move, rootNode.y + (rootNode.y - leafNode.y) * 0.5);
183+
let pos0 = vis.graph.getRotPos(); // original position
184+
let pos = rotateStep(pos0, 2); // compute new position
185+
vis.graph.setNodePosition(tt6, pos.rX, pos.rY);
186+
vis.graph.setNodePosition(tt2, pos.cX, pos.cY);
155187
},
156188
[R.key, A.key, D ? D.key : false],
157189
depth
@@ -274,19 +306,14 @@ export default {
274306

275307
// -- following code is for visualising the rotation step by step --
276308
// find the position of the nodes in the graph
277-
let rootNode = vis.graph.findNode(tt6);
278-
let leafNode = vis.graph.findNode(tt2);
309+
let rootNode = vis.graph.findNode(tt2);
310+
let leafNode = vis.graph.findNode(tt6);
279311
// store the previous height of the root node
280-
vis.graph.storePrevHeight(leafNode.y);
281-
let newY = (rootNode.y + leafNode.y) / 2;
282-
let moveX = 0;
283-
// avoid overlapping
284-
if ((rootNode.x - leafNode.x) < nodeSize) {
285-
moveX = nodeSize - (rootNode.x - leafNode.x);
286-
}
287-
// set the new position of the nodes
288-
vis.graph.setNodePosition(tt6, rootNode.x + moveX, newY);
289-
vis.graph.setNodePosition(tt2, leafNode.x - moveX, newY);
312+
let pos0 = {rX:rootNode.x, rY:rootNode.y, cX:leafNode.x, cY:leafNode.y};
313+
vis.graph.setRotPos(pos0);
314+
let pos = rotateStep(pos0, 1); // compute new position
315+
vis.graph.setNodePosition(tt2, pos.rX, pos.rY);
316+
vis.graph.setNodePosition(tt6, pos.cX, pos.cY);
290317
},
291318
[A.key, R.key],
292319
depth
@@ -304,15 +331,13 @@ export default {
304331
}
305332

306333
// -- following code is for visualising the rotation step by step --
307-
// find the position of the nodes in the graph
308-
let rootNode = vis.graph.findNode(tt6);
309-
let leafNode = vis.graph.findNode(tt2);
310334
// freeze the layout to avoid the nodes moving automatically
311335
vis.graph.setPauseLayout(true);
312-
let move = (leafNode.x - rootNode.x) / 5;
313336
// set the new position of the nodes
314-
vis.graph.setNodePosition(tt6, rootNode.x + move, vis.graph.getPrevHeight());
315-
vis.graph.setNodePosition(tt2, leafNode.x - move, leafNode.y - (rootNode.y - leafNode.y) * 0.5);
337+
let pos0 = vis.graph.getRotPos(); // original position
338+
let pos = rotateStep(pos0, 2); // compute new position
339+
vis.graph.setNodePosition(tt2, pos.rX, pos.rY);
340+
vis.graph.setNodePosition(tt6, pos.cX, pos.cY);
316341
},
317342
[R.key, A.key, D ? D.key : false],
318343
depth

src/algorithms/pseudocode/AVLTreeInsertion.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import parse from '../../pseudocode/parse';
33
export default parse(`
44
55
\\Note{ REAL specification of AVL tree insertion and search
6-
XXX draft
6+
XXX Note: has undergone significant restructure and bookmarks have not been
7+
renamed according to new structure
78
\\Note}
89
910
\\Note{ modified from BST - best check actual running BST Real code for
10-
search and use that
11+
search and use that XXX still needs unification with BST
1112
1213
Terminology (might change???)
1314
For BST we confound t.key and t->key, eg, we have c <- c.left. Its not
@@ -20,6 +21,7 @@ left(t) = *(t->left) (or Empty) ?????
2021
right() similarly
2122
root(t).key, root(t).height, etc
2223
left(t).height, etc ???
24+
XXX maybe use height(t), key(t), left(t), right(t)
2325
\\Note}
2426
2527
\\Overview{ A binary tree is either is either empty (Empty) or else it

src/algorithms/pseudocode/AVLTreeSearch.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ AVLT_Search(t, k) // return subtree whose root has key k; or NotFound \\B AVL_
1010
while t not Empty \\B while t not Empty
1111
\\In{
1212
n = root(t) \\B n = root(t)
13-
\\Note{ Avoids confounding pointers and nodes
13+
\\Note{ Avoids confounding pointers and nodes XXX not worth it???
14+
could use key(t), left(t), right(t) below; make as similar to
15+
AVLTree code as possible
1416
\\Note}
1517
if n.key = k \\B if n.key = k
1618
\\In{
@@ -34,4 +36,4 @@ AVLT_Search(t, k) // return subtree whose root has key k; or NotFound \\B AVL_
3436
\\In}
3537
\\In}
3638
\\Code}
37-
`);
39+
`);

src/components/DataStructures/Graph/GraphTracer.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ class GraphTracer extends Tracer {
6767
this.istc = false;
6868
this.radius = null;
6969

70+
// used in AVL trees
7071
this.pauseLayout = false;
71-
this.prebHeight = 0; // restore the previous height of the node
72+
this.rotPos = {};
7273
}
7374

7475
/*
@@ -1180,19 +1181,17 @@ class GraphTracer extends Tracer {
11801181
}
11811182

11821183
/**
1183-
* return the previous height of the tree in insertion
1184-
* @param {int} prebHeight the previous height of the tree
1184+
* save position of root and child pre-rotation (AVL trees)
11851185
*/
1186-
storePrevHeight(prebHeight) {
1187-
this.prebHeight = prebHeight;
1186+
setRotPos(pos) {
1187+
this.rotPos = pos;
11881188
}
11891189

11901190
/**
1191-
* return the previous height of the tree in insertion
1192-
* @returns {int} the previous height of the tree
1191+
* return position of root and child pre-rotation (AVL trees)
11931192
*/
1194-
getPrevHeight() {
1195-
return this.prebHeight;
1193+
getRotPos() {
1194+
return this.rotPos;
11961195
}
11971196
}
11981197

0 commit comments

Comments
 (0)