@@ -121,6 +121,94 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
121
121
return true;
122
122
};
123
123
124
+ /**
125
+ * Gets the nodes to be restructured during an AVL restructure
126
+ * after a remove/delete takes place.
127
+ *
128
+ * @public
129
+ * @method
130
+ * @param {Array} traveledNodes Array of previously traveled nodes
131
+ * that are used to help determine the nodes to be restructured.
132
+ */
133
+ exports.AVLTree.prototype._getNodesToRestructureRemove =
134
+ function (traveledNodes) {
135
+ // z is last traveled node - imbalance found at z
136
+ var zIndex = traveledNodes.length;
137
+ zIndex -= 1;
138
+ var z = traveledNodes[zIndex];
139
+ // y should be child of z with larger height
140
+ // (cannot be ancestor of removed node)
141
+ var y;
142
+ if (z._left !== null && z._right !== null){
143
+ y = (z._left === y) ? z._right : z._left;
144
+ }else if (z._left !== null && z._right === null){
145
+ y = z._left;
146
+ }else if (z._right !== null && z._left === null){
147
+ y = z._right;
148
+ }
149
+ // x should be tallest child of y.
150
+ // If children same height, x should be child of y
151
+ // that has same orientation as z to y.
152
+ var x;
153
+ if (y._left !== null && y._right !== null){
154
+ if (y._left._height > y._right._height){
155
+ x = y._left;
156
+ }else if (y._left._height < y._right._height){
157
+ x = y._right;
158
+ }else if (y._left._height === y._right._height){
159
+ x = (z._left === y) ? y._left : y._right;
160
+ }
161
+ }else if (y._left !== null && y._right === null){
162
+ x = y._left;
163
+ }else if (y._right !== null && y._left === null){
164
+ x = y._right;
165
+ }
166
+ return [x, y, z];
167
+ };
168
+
169
+ /**
170
+ * Gets the nodes to be restructured during an AVL restructure
171
+ * after an insert takes place.
172
+ *
173
+ * @public
174
+ * @method
175
+ * @param {Array} traveledNodes Array of previously traveled nodes
176
+ * that are used to help determine the nodes to be restructured.
177
+ */
178
+ exports.AVLTree.prototype._getNodesToRestructureInsert =
179
+ function (traveledNodes) {
180
+ // z is last traveled node - imbalance found at z
181
+ var zIndex = traveledNodes.length;
182
+ zIndex -= 1;
183
+ var z = traveledNodes[zIndex];
184
+ // y should be child of z with larger height
185
+ // (must be ancestor of inserted node)
186
+ // therefore, last traveled node is correct.
187
+ var yIndex = traveledNodes.length;
188
+ yIndex -= 2;
189
+ var y = traveledNodes[yIndex];
190
+ // x should be tallest child of y.
191
+ // If children same height, x should be ancestor
192
+ // of inserted node (in traveled path).
193
+ var x;
194
+ if (y._left !== null && y._right !== null){
195
+ if (y._left._height > y._right._height){
196
+ x = y._left;
197
+ }else if (y._left._height < y._right._height){
198
+ x = y._right;
199
+ }else if (y._left._height === y._right._height){
200
+ var xIndex = traveledNodes.length;
201
+ xIndex -= 3;
202
+ x = traveledNodes[xIndex];
203
+ }
204
+ }else if (y._left !== null && y._right === null){
205
+ x = y._left;
206
+ }else if (y._right !== null && y._left === null){
207
+ x = y._right;
208
+ }
209
+ return [x, y, z];
210
+ };
211
+
124
212
/**
125
213
* Maintains the height balance property by
126
214
* walking to root and checking for invalid height
@@ -130,21 +218,20 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
130
218
* @public
131
219
* @method
132
220
* @param {Node} node Started node.
221
+ * @param {Boolean} isRemove Represents if method was called after remove.
133
222
*/
134
- exports.AVLTree.prototype._maintainHeightBalanceProperty = function (node) {
223
+ exports.AVLTree.prototype._maintainHeightBalanceProperty =
224
+ function (node, isRemove) {
135
225
var current = node;
136
- var path = []; //During restructure, use last 3 nodes traveled.
226
+ var traveledNodes = [];
137
227
while (current !== null){
138
- path .push(current);
228
+ traveledNodes .push(current);
139
229
current._height = this._getHeightAtNode(current);
140
230
if (!this._isBalancedAtNode(current)){
141
- if (path.length > = 3){
142
- var nodesToRestructure = path.slice(0, 3);
143
- var x = nodesToRestructure[0];
144
- var y = nodesToRestructure[1];
145
- var z = nodesToRestructure[2];
146
- this._restructure(x, y, z);
147
- }
231
+ var nodesToBeRestructured = (isRemove)
232
+ ? this._getNodesToRestructureRemove(traveledNodes)
233
+ : this._getNodesToRestructureInsert(traveledNodes);
234
+ this._restructure(nodesToBeRestructured);
148
235
}
149
236
current = current._parent;
150
237
}
@@ -156,11 +243,13 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
156
243
*
157
244
* @public
158
245
* @method
159
- * @param {Node} x node with lowest height to be restructured.
160
- * @param {Node} y parent of x parameter.
161
- * @param {Node} z grandparent of x, largest height.
246
+ * @param {Array} nodesToBeRestructured
247
+ * array of nodes, in format, [x, y, z], to be restructured
162
248
*/
163
- exports.AVLTree.prototype._restructure = function (x, y, z) {
249
+ exports.AVLTree.prototype._restructure = function (nodesToBeRestructured) {
250
+ var x = nodesToBeRestructured[0];
251
+ var y = nodesToBeRestructured[1];
252
+ var z = nodesToBeRestructured[2];
164
253
//Determine Rotation Pattern
165
254
if (z._right === y && y._right === x){
166
255
this._rightRight(x, y, z);
@@ -365,7 +454,7 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
365
454
}
366
455
if (!current[insertKey]) {
367
456
current[insertKey] = new exports.Node(value, null, null, current);
368
- this._maintainHeightBalanceProperty(current[insertKey]);
457
+ this._maintainHeightBalanceProperty(current[insertKey], false );
369
458
} else {
370
459
this.insert(value, current[insertKey]);
371
460
}
@@ -509,9 +598,11 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
509
598
*/
510
599
exports.AVLTree.prototype._replaceChild =
511
600
function (parent, oldChild, newChild) {
512
- if (! parent) {
601
+ if (parent === null ) {
513
602
this._root = newChild;
514
- this._root._parent = null;
603
+ if (this._root !== null){
604
+ this._root._parent = null;
605
+ }
515
606
} else {
516
607
if (parent._left === oldChild) {
517
608
parent._left = newChild;
@@ -529,33 +620,31 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
529
620
* Average runtime complexity: O(log N).
530
621
*
531
622
* @public
532
- * @param {Node} node to be removed
623
+ * @param {Number|String} value of node to be removed
533
624
* @returns {Boolean} True/false depending
534
625
* on whether the given node is removed.
535
626
*/
536
- exports.AVLTree.prototype.remove = function (node) {
627
+ exports.AVLTree.prototype.remove = function (value) {
628
+ var node = this.find(value);
537
629
if (!node) {
538
630
return false;
539
631
}
540
-
541
632
if (node._left && node._right) {
542
633
var min = this._findMin(node._right);
543
634
var temp = node.value;
544
-
545
635
node.value = min.value;
546
636
min.value = temp;
547
637
return this.remove(min);
548
638
} else {
549
- if (node._parent !== null) {
550
- if (node._left) {
551
- this._replaceChild(node._parent, node, node._left);
552
- } else if (node._right) {
553
- this._replaceChild(node._parent, node, node._right);
554
- } else {
555
- this._replaceChild(node._parent, node, null);
556
- }
557
- }else {
558
- this._root = null;
639
+ if (node._left) {
640
+ this._replaceChild(node._parent, node, node._left);
641
+ this._maintainHeightBalanceProperty(node._left, true);
642
+ } else if (node._right) {
643
+ this._replaceChild(node._parent, node, node._right);
644
+ this._maintainHeightBalanceProperty(node._right, true);
645
+ } else {
646
+ this._replaceChild(node._parent, node, null);
647
+ this._maintainHeightBalanceProperty(node._parent, true);
559
648
}
560
649
return true;
561
650
}
@@ -684,12 +773,12 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
684
773
* @returns {Node} The lowest common ancestor of the two nodes or null.
685
774
*/
686
775
exports.AVLTree.prototype.lowestCommonAncestor =
687
- function (firstNode, secondNode) {
776
+ function (firstNode, secondNode) {
688
777
return this._lowestCommonAncestor(firstNode, secondNode, this._root);
689
778
};
690
779
691
780
exports.AVLTree.prototype._lowestCommonAncestor =
692
- function (firstNode, secondNode, current) {
781
+ function (firstNode, secondNode, current) {
693
782
var firstNodeInLeft = this._existsInSubtree(firstNode, current._left);
694
783
var secondNodeInLeft = this._existsInSubtree(secondNode, current._left);
695
784
var firstNodeInRight = this._existsInSubtree(firstNode, current._right);
@@ -735,7 +824,7 @@ <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-co
735
824
< br class ="clear ">
736
825
737
826
< footer >
738
- Documentation generated by < a href ="https://github.com/jsdoc3/jsdoc "> JSDoc 3.3.0-alpha13</ a > on Fri Feb 27 2015 09:39:04 GMT-0800 (PST )
827
+ Documentation generated by < a href ="https://github.com/jsdoc3/jsdoc "> JSDoc 3.3.0-alpha13</ a > on Tue Mar 10 2015 11:52:43 GMT-0700 (PDT )
739
828
</ footer >
740
829
741
830
< script > prettyPrint ( ) ; </ script >
0 commit comments