-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathavlBalance.js
147 lines (119 loc) · 3.48 KB
/
avlBalance.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import Tree from "./tree.js";
const tree = new Tree();
export default function avlBalancedTree(values) {
let rotated = false;
if (values instanceof Tree) {
const { preorder } = values.traverse();
values = preorder;
}
for (let i = 0; i < values.length; i++) {
const checkNode = tree.insert(values[i]);
const node = checkRotation(checkNode);
if (node.rotationRequired == true) {
rotated = true;
avlRotate(node);
}
delete node.rotationRequired;
}
return { balancedTree: tree, rotated };
}
//Function to check if node is balanced or not
function checkRotation(node) {
if (node == null) return { rotationRequired: false };
const leftMaxBranch = getMaxBranch(node.LEFT);
const rightMaxBranch = getMaxBranch(node.RIGHT);
const difference =
(node.LEFT != null ? leftMaxBranch.length + 1 : 0) -
(node.RIGHT != null ? rightMaxBranch.length + 1 : 0);
if (difference == 2) {
node.rotationRequired = true;
node.leftMaxBranch = leftMaxBranch;
return node;
} else if (difference == -2) {
node.rotationRequired = true;
node.rightMaxBranch = rightMaxBranch;
return node;
} else {
let statusNode = checkRotation(node.PARENT);
if (statusNode.rotationRequired == true) return statusNode;
return { rotationRequired: false };
}
}
//Function to check the maximum branch upto leaf from given node
function getMaxBranch(node) {
const { preorder } = tree.traverse(node);
const maxPath = new Array();
let maxLeaf = node; //Track leaf with max depth
if (preorder.length == 0) return maxPath;
for (let key of preorder) {
const result = tree.search(key, node);
if (result.isLeaf()) {
maxLeaf = maxLeaf.depth < result.depth ? result : maxLeaf;
}
}
let currentNode = maxLeaf;
while (currentNode.value != node.value) {
maxPath.push(currentNode.getSide());
currentNode = currentNode.PARENT;
}
return maxPath.reverse();
}
//Fucntion to perform rotation
function avlRotate(node) {
if (node.rightMaxBranch != undefined) {
if (node.rightMaxBranch[0] == "LEFT") rotateRight(node.RIGHT);
rotateLeft(node);
delete node.rightMaxBranch;
} else {
if (node.leftMaxBranch[0] == "RIGHT") rotateLeft(node.LEFT);
rotateRight(node);
delete node.leftMaxBranch;
}
tree.root.depth = 0;
tree.root.PARENT = null;
updateDepth(tree.root.LEFT);
updateDepth(tree.root.RIGHT);
const checkNode = checkRotation(tree.root);
if (checkNode.rotationRequired == true) {
delete checkNode.rotationRequired;
avlRotate(checkNode);
}
}
function rotateLeft(node) {
const right = node.RIGHT.LEFT;
if (node.PARENT == null) {
tree.root = node.RIGHT;
node.PARENT = node.RIGHT;
node.PARENT.LEFT = node;
} else {
const parent = node.PARENT;
const side = node.getSide();
node.PARENT = node.RIGHT;
node.PARENT.PARENT = parent;
node.PARENT.LEFT = node;
parent[side] = node.PARENT;
}
node.RIGHT = right;
}
function rotateRight(node) {
const left = node.LEFT.RIGHT;
if (node.PARENT == null) {
tree.root = node.LEFT;
node.PARENT = node.LEFT;
node.PARENT.RIGHT = node;
} else {
const parent = node.PARENT;
const side = node.getSide();
node.PARENT = node.LEFT;
node.PARENT.RIGHT = node;
node.PARENT.PARENT = parent;
parent[side] = node.PARENT;
}
node.LEFT = left;
}
function updateDepth(node) {
if (node == null) return;
node.depth = node.PARENT.depth + 1;
updateDepth(node.RIGHT);
updateDepth(node.LEFT);
}