-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAvlTree.js
163 lines (138 loc) · 4.25 KB
/
AvlTree.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import BinarySearchTree from '../binary-search-tree/BinarySearchTree';
export default class AvlTree extends BinarySearchTree {
/**
* @param {*} value
*/
insert(value) {
// Do the normal BST insert.
super.insert(value);
// Let's move up to the root and check balance factors along the way.
let currentNode = this.root.find(value);
while (currentNode) {
this.balance(currentNode);
currentNode = currentNode.parent;
}
}
/**
* @param {*} value
* @return {boolean}
*/
remove(value) {
// Do standard BST removal.
super.remove(value);
// Balance the tree starting from the root node.
this.balance(this.root);
}
/**
* @param {BinarySearchTreeNode} node
*/
balance(node) {
// If balance factor is not OK then try to balance the node.
if (node.balanceFactor > 1) {
// Left rotation.
if (node.left.balanceFactor > 0) {
// Left-Left rotation
this.rotateLeftLeft(node);
} else if (node.left.balanceFactor < 0) {
// Left-Right rotation.
this.rotateLeftRight(node);
}
} else if (node.balanceFactor < -1) {
// Right rotation.
if (node.right.balanceFactor < 0) {
// Right-Right rotation
this.rotateRightRight(node);
} else if (node.right.balanceFactor > 0) {
// Right-Left rotation.
this.rotateRightLeft(node);
}
}
}
/**
* @param {BinarySearchTreeNode} rootNode
*/
rotateLeftLeft(rootNode) {
// Detach left node from root node.
const leftNode = rootNode.left;
rootNode.setLeft(null);
// Make left node to be a child of rootNode's parent.
if (rootNode.parent) {
rootNode.parent.setLeft(leftNode);
} else if (rootNode === this.root) {
// If root node is root then make left node to be a new root.
this.root = leftNode;
}
// If left node has a right child then detach it and
// attach it as a left child for rootNode.
if (leftNode.right) {
rootNode.setLeft(leftNode.right);
}
// Attach rootNode to the right of leftNode.
leftNode.setRight(rootNode);
}
/**
* @param {BinarySearchTreeNode} rootNode
*/
rotateLeftRight(rootNode) {
// Detach left node from rootNode since it is going to be replaced.
const leftNode = rootNode.left;
rootNode.setLeft(null);
// Detach right node from leftNode.
const leftRightNode = leftNode.right;
leftNode.setRight(null);
// Preserve leftRightNode's left subtree.
if (leftRightNode.left) {
leftNode.setRight(leftRightNode.left);
leftRightNode.setLeft(null);
}
// Attach leftRightNode to the rootNode.
rootNode.setLeft(leftRightNode);
// Attach leftNode as left node for leftRight node.
leftRightNode.setLeft(leftNode);
// Do left-left rotation.
this.rotateLeftLeft(rootNode);
}
/**
* @param {BinarySearchTreeNode} rootNode
*/
rotateRightLeft(rootNode) {
// Detach right node from rootNode since it is going to be replaced.
const rightNode = rootNode.right;
rootNode.setRight(null);
// Detach left node from rightNode.
const rightLeftNode = rightNode.left;
rightNode.setLeft(null);
if (rightLeftNode.right) {
rightNode.setLeft(rightLeftNode.right);
rightLeftNode.setRight(null);
}
// Attach rightLeftNode to the rootNode.
rootNode.setRight(rightLeftNode);
// Attach rightNode as right node for rightLeft node.
rightLeftNode.setRight(rightNode);
// Do right-right rotation.
this.rotateRightRight(rootNode);
}
/**
* @param {BinarySearchTreeNode} rootNode
*/
rotateRightRight(rootNode) {
// Detach right node from root node.
const rightNode = rootNode.right;
rootNode.setRight(null);
// Make right node to be a child of rootNode's parent.
if (rootNode.parent) {
rootNode.parent.setRight(rightNode);
} else if (rootNode === this.root) {
// If root node is root then make right node to be a new root.
this.root = rightNode;
}
// If right node has a left child then detach it and
// attach it as a right child for rootNode.
if (rightNode.left) {
rootNode.setRight(rightNode.left);
}
// Attach rootNode to the left of rightNode.
rightNode.setLeft(rootNode);
}
}