fix rbt traversal.
This commit is contained in:
parent
0d0b6c562e
commit
1e8c3a4487
102
lib/bcoin/rbt.js
102
lib/bcoin/rbt.js
@ -479,24 +479,13 @@ RBT.prototype.snapshot = function snapshot() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
RBT.prototype.traverse = function traverse(test) {
|
RBT.prototype.traverse = function traverse(test) {
|
||||||
var current = this.root;
|
var current = this.min(this.root);
|
||||||
var stack = [];
|
|
||||||
var items = [];
|
var items = [];
|
||||||
|
|
||||||
for (;;) {
|
while (!current.isNull()) {
|
||||||
if (!current.isNull()) {
|
if (test(current))
|
||||||
if (test(current))
|
items.push(current.copy());
|
||||||
items.push(current.copy());
|
current = this.successor(current);
|
||||||
stack.push(current);
|
|
||||||
current = current.left;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack.length === 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
current = stack.pop();
|
|
||||||
current = current.right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
@ -519,8 +508,8 @@ RBT.prototype.dump = function dump() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
RBT.prototype.range = function range(gte, lte) {
|
RBT.prototype.range = function range(gte, lte) {
|
||||||
var current = this.root;
|
var root = this.root;
|
||||||
var stack = [];
|
var current = SENTINEL;
|
||||||
var items = [];
|
var items = [];
|
||||||
var cmp;
|
var cmp;
|
||||||
|
|
||||||
@ -530,63 +519,44 @@ RBT.prototype.range = function range(gte, lte) {
|
|||||||
if (typeof lte === 'string')
|
if (typeof lte === 'string')
|
||||||
lte = new Buffer(lte, 'ascii');
|
lte = new Buffer(lte, 'ascii');
|
||||||
|
|
||||||
for (;;) {
|
if (gte) {
|
||||||
if (!current.isNull()) {
|
// Find the node closest to our gte key.
|
||||||
cmp = this.rangeCompare(current.key, gte, lte);
|
while (!root.isNull()) {
|
||||||
|
cmp = this.compare(gte, root.key);
|
||||||
|
|
||||||
if (cmp === 0) {
|
if (cmp === 0) {
|
||||||
items.push(current.copy());
|
current = root;
|
||||||
stack.push(current);
|
break;
|
||||||
}
|
}
|
||||||
if (cmp <= 0)
|
|
||||||
current = current.left;
|
if (cmp < 0) {
|
||||||
else
|
current = root;
|
||||||
current = current.right;
|
root = root.left;
|
||||||
continue;
|
} else {
|
||||||
|
root = root.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Descend into the left subtree.
|
||||||
|
current = this.min(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk the tree in order.
|
||||||
|
while (!current.isNull()) {
|
||||||
|
if (lte) {
|
||||||
|
// Stop once we hit a key above our lte key.
|
||||||
|
cmp = this.compare(current.key, lte);
|
||||||
|
if (cmp > 0)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stack.length === 0)
|
items.push(current.copy());
|
||||||
break;
|
current = this.successor(current);
|
||||||
|
|
||||||
current = stack.pop();
|
|
||||||
current = current.right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Comparator for {@link RBT#range}.
|
|
||||||
* @param {Buffer} key
|
|
||||||
* @param {Buffer} gteKey
|
|
||||||
* @param {Buffer} lteKey
|
|
||||||
* @returns {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
RBT.prototype.rangeCompare = function rangeCompare(key, gteKey, lteKey) {
|
|
||||||
var gte, lte;
|
|
||||||
|
|
||||||
if (gteKey)
|
|
||||||
gte = this.compare(key, gteKey);
|
|
||||||
else
|
|
||||||
gte = 0;
|
|
||||||
|
|
||||||
if (lteKey)
|
|
||||||
lte = this.compare(key, lteKey);
|
|
||||||
else
|
|
||||||
lte = 0;
|
|
||||||
|
|
||||||
if (gte >= 0 && lte <= 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (lte > 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (gte < 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the database (leveldown method).
|
* Open the database (leveldown method).
|
||||||
* @param {Object?} options
|
* @param {Object?} options
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user