@@ -121,6 +121,94 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
121121 return true;
122122 };
123123
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+
124212 /**
125213 * Maintains the height balance property by
126214 * walking to root and checking for invalid height
@@ -130,21 +218,20 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
130218 * @public
131219 * @method
132220 * @param {Node} node Started node.
221+ * @param {Boolean} isRemove Represents if method was called after remove.
133222 */
134- exports.AVLTree.prototype._maintainHeightBalanceProperty = function (node) {
223+ exports.AVLTree.prototype._maintainHeightBalanceProperty =
224+ function (node, isRemove) {
135225 var current = node;
136- var path = []; //During restructure, use last 3 nodes traveled.
226+ var traveledNodes = [];
137227 while (current !== null){
138- path .push(current);
228+ traveledNodes .push(current);
139229 current._height = this._getHeightAtNode(current);
140230 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);
148235 }
149236 current = current._parent;
150237 }
@@ -156,11 +243,13 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
156243 *
157244 * @public
158245 * @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
162248 */
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];
164253 //Determine Rotation Pattern
165254 if (z._right === y && y._right === x){
166255 this._rightRight(x, y, z);
@@ -365,7 +454,7 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
365454 }
366455 if (!current[insertKey]) {
367456 current[insertKey] = new exports.Node(value, null, null, current);
368- this._maintainHeightBalanceProperty(current[insertKey]);
457+ this._maintainHeightBalanceProperty(current[insertKey], false );
369458 } else {
370459 this.insert(value, current[insertKey]);
371460 }
@@ -509,9 +598,11 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
509598 */
510599 exports.AVLTree.prototype._replaceChild =
511600 function (parent, oldChild, newChild) {
512- if (! parent) {
601+ if (parent === null ) {
513602 this._root = newChild;
514- this._root._parent = null;
603+ if (this._root !== null){
604+ this._root._parent = null;
605+ }
515606 } else {
516607 if (parent._left === oldChild) {
517608 parent._left = newChild;
@@ -529,33 +620,31 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
529620 * Average runtime complexity: O(log N).
530621 *
531622 * @public
532- * @param {Node} node to be removed
623+ * @param {Number|String} value of node to be removed
533624 * @returns {Boolean} True/false depending
534625 * on whether the given node is removed.
535626 */
536- exports.AVLTree.prototype.remove = function (node) {
627+ exports.AVLTree.prototype.remove = function (value) {
628+ var node = this.find(value);
537629 if (!node) {
538630 return false;
539631 }
540-
541632 if (node._left && node._right) {
542633 var min = this._findMin(node._right);
543634 var temp = node.value;
544-
545635 node.value = min.value;
546636 min.value = temp;
547637 return this.remove(min);
548638 } 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);
559648 }
560649 return true;
561650 }
@@ -684,12 +773,12 @@ <h1 class="page-title">Source: data-structures/avl-tree.js</h1>
684773 * @returns {Node} The lowest common ancestor of the two nodes or null.
685774 */
686775 exports.AVLTree.prototype.lowestCommonAncestor =
687- function (firstNode, secondNode) {
776+ function (firstNode, secondNode) {
688777 return this._lowestCommonAncestor(firstNode, secondNode, this._root);
689778 };
690779
691780 exports.AVLTree.prototype._lowestCommonAncestor =
692- function (firstNode, secondNode, current) {
781+ function (firstNode, secondNode, current) {
693782 var firstNodeInLeft = this._existsInSubtree(firstNode, current._left);
694783 var secondNodeInLeft = this._existsInSubtree(secondNode, current._left);
695784 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
735824< br class ="clear ">
736825
737826< 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 )
739828</ footer >
740829
741830< script > prettyPrint ( ) ; </ script >
0 commit comments