looking at the avltree implementation; ok, I think I understand it enough to edit it.

This commit is contained in:
Danny Yoo 2011-11-03 12:55:55 -04:00
parent 3653b24476
commit 78d875aac1

View File

@ -1,7 +1,12 @@
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// dyoo: the following code comes from the Google Closure Library. I've done // dyoo: the following code comes from the Google Closure Library. I've done
// light edits to flatten the namespace from goog.structs to just // edits to flatten the namespace from goog.structs to just
// AvlTree. // AvlTree, commented out inorderTraverse and reverseOrderTraverse.
//
// I'm considering changing the code to work with CPSed control flow.
//
// ----------------------------------------------------------------------
// Original license follows:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -383,64 +388,64 @@ AvlTree.prototype.inOrderTraverse =
prev = temp; prev = temp;
} }
} }
}; };
/** // /**
* Performs a reverse-order traversal of the tree and calls {@code func} with // * Performs a reverse-order traversal of the tree and calls {@code func} with
* each traversed node, optionally starting from the largest node with a value // * each traversed node, optionally starting from the largest node with a value
* <= to the specified start value. The traversal ends after traversing the // * <= to the specified start value. The traversal ends after traversing the
* tree's minimum node or when func returns a value that evaluates to true. // * tree's minimum node or when func returns a value that evaluates to true.
* // *
* @param {Function} func Function to call on each traversed node. // * @param {Function} func Function to call on each traversed node.
* @param {Object=} opt_startValue If specified, traversal will begin on the // * @param {Object=} opt_startValue If specified, traversal will begin on the
* node with the largest value <= opt_startValue. // * node with the largest value <= opt_startValue.
*/ // */
AvlTree.prototype.reverseOrderTraverse = // AvlTree.prototype.reverseOrderTraverse =
function(func, opt_startValue) { // function(func, opt_startValue) {
// If our tree is empty, return immediately // // If our tree is empty, return immediately
if (!this.root_) { // if (!this.root_) {
return; // return;
} // }
// Depth traverse the tree to find node to begin reverse-order traversal from // // Depth traverse the tree to find node to begin reverse-order traversal from
var startNode; // var startNode;
if (opt_startValue) { // if (opt_startValue) {
this.traverse_(goog.bind(function(node) { // this.traverse_(goog.bind(function(node) {
var retNode = null; // var retNode = null;
if (this.comparator_(node.value, opt_startValue) > 0) { // if (this.comparator_(node.value, opt_startValue) > 0) {
retNode = node.left; // retNode = node.left;
} else if (this.comparator_(node.value, opt_startValue) < 0) { // } else if (this.comparator_(node.value, opt_startValue) < 0) {
retNode = node.right; // retNode = node.right;
startNode = node; // startNode = node;
} else { // } else {
startNode = node; // startNode = node;
} // }
return retNode; // If null, we'll stop traversing the tree // return retNode; // If null, we'll stop traversing the tree
}, this)); // }, this));
} else { // } else {
startNode = this.getMaxNode_(); // startNode = this.getMaxNode_();
} // }
// Traverse the tree and call func on each traversed node's value // // Traverse the tree and call func on each traversed node's value
var node = startNode, prev = startNode.right ? startNode.right : startNode; // var node = startNode, prev = startNode.right ? startNode.right : startNode;
while (node != null) { // while (node != null) {
if (node.right != null && node.right != prev && node.left != prev) { // if (node.right != null && node.right != prev && node.left != prev) {
node = node.right; // node = node.right;
} else { // } else {
if (node.left != prev) { // if (node.left != prev) {
if (func(node.value)) { // if (func(node.value)) {
return; // return;
} // }
} // }
var temp = node; // var temp = node;
node = node.left != null && node.left != prev ? // node = node.left != null && node.left != prev ?
node.left : // node.left :
node.parent; // node.parent;
prev = temp; // prev = temp;
} // }
} // }
}; // };
/** /**
@ -466,7 +471,24 @@ AvlTree.prototype.traverse_ =
while (node && node != endNode) { while (node && node != endNode) {
node = traversalFunc.call(this, node); node = traversalFunc.call(this, node);
} }
}; };
// CPS'ed version of the traverse function
AvlTree.prototype.traverse_k_ =
function(traversalFunc_k, opt_startNode, opt_endNode, k) {
var node = opt_startNode ? opt_startNode : this.root_;
var endNode = opt_endNode ? opt_endNode : null;
var loop = function(node) {
if (node && node != endNode) {
traversalFunc_k.call(this, node, loop);
} else {
k();
}
}
return loop(node);
};
/** /**