Skip to content

Commit 0df3be9

Browse files
♻️ refactor(rangetraversal): Avoid unnecessary comparisons.
1 parent 604fc5a commit 0df3be9

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

src/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export {default as swap_color} from './swap/swap_color.js';
3030
export {default as swap_left} from './swap/swap_left.js';
3131
export {default as swap_non_adjacent} from './swap/swap_non_adjacent.js';
3232
export {default as inordertraversal} from './traversal/inordertraversal.js';
33+
export {default as leftOpenRangeTraversal} from './traversal/leftOpenRangeTraversal.js';
3334
export {default as rangetraversal} from './traversal/rangetraversal.js';
35+
export {default as rightOpenRangeTraversal} from './traversal/rightOpenRangeTraversal.js';
3436
export {default as Node} from './types/Node.js';
3537
export {default as RedBlackTree} from './types/RedBlackTree.js';
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import assert from 'assert';
2+
import Node from '../types/Node.js';
3+
import inordertraversal from './inordertraversal.js';
4+
5+
/**
6+
* Yields all the keys in the tree rooted at <code>root</code> that lie in the
7+
* interval <code>(-oo, right[</code>, in order.
8+
*
9+
* @param {Function} compare - The comparison function.
10+
* @param {Node} root - The root of the tree.
11+
* @param {any} right - The non-inclusive upper bound of the interval.
12+
* @returns {IterableIterator}
13+
*/
14+
export default function* leftOpenRangeTraversal(compare, root, right) {
15+
if (compare(root.key, right) >= 0) {
16+
// If the root lies to the right of the interval, we can discard the
17+
// entire right subtree.
18+
if (root.left !== null) {
19+
assert(root.left instanceof Node);
20+
yield* leftOpenRangeTraversal(compare, root.left, right);
21+
}
22+
} else {
23+
// Otherwise yield entire left subtree, yield the root, and recurse on
24+
// the right subtree.
25+
if (root.left !== null) {
26+
assert(root.left instanceof Node);
27+
yield* inordertraversal(root.left);
28+
}
29+
30+
yield root.key;
31+
if (root.right !== null) {
32+
assert(root.right instanceof Node);
33+
yield* leftOpenRangeTraversal(compare, root.right, right);
34+
}
35+
}
36+
}

src/traversal/rangetraversal.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import assert from 'assert';
22
import Node from '../types/Node.js';
3+
import leftOpenRangeTraversal from './leftOpenRangeTraversal.js';
4+
import rightOpenRangeTraversal from './rightOpenRangeTraversal.js';
35

46
/**
57
* Yields all the keys in the tree rooted at <code>root</code> that lie in the
@@ -31,13 +33,13 @@ export default function* rangetraversal(compare, root, left, right) {
3133
// between.
3234
if (root.left !== null) {
3335
assert(root.left instanceof Node);
34-
yield* rangetraversal(compare, root.left, left, right);
36+
yield* rightOpenRangeTraversal(compare, root.left, left);
3537
}
3638

3739
yield root.key;
3840
if (root.right !== null) {
3941
assert(root.right instanceof Node);
40-
yield* rangetraversal(compare, root.right, left, right);
42+
yield* leftOpenRangeTraversal(compare, root.right, right);
4143
}
4244
}
4345
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import assert from 'assert';
2+
import Node from '../types/Node.js';
3+
import inordertraversal from './inordertraversal.js';
4+
5+
/**
6+
* Yields all the keys in the tree rooted at <code>root</code> that lie in the
7+
* interval <code>[left, +oo)</code>, in order.
8+
*
9+
* @param {Function} compare - The comparison function.
10+
* @param {Node} root - The root of the tree.
11+
* @param {any} left - The inclusive lower bound of the interval.
12+
* @returns {IterableIterator}
13+
*/
14+
export default function* rightOpenRangeTraversal(compare, root, left) {
15+
if (compare(root.key, left) < 0) {
16+
// If the root lies to the left of the interval, we can discard the
17+
// entire left subtree.
18+
if (root.right !== null) {
19+
assert(root.right instanceof Node);
20+
yield* rightOpenRangeTraversal(compare, root.right, left);
21+
}
22+
} else {
23+
// Otherwise recurse on left subtree, yield the root, and yield the
24+
// entire right subtree.
25+
if (root.left !== null) {
26+
assert(root.left instanceof Node);
27+
yield* rightOpenRangeTraversal(compare, root.left, left);
28+
}
29+
30+
yield root.key;
31+
if (root.right !== null) {
32+
assert(root.right instanceof Node);
33+
yield* inordertraversal(root.right);
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)