feat: Add a rangeSearch method to binary search tree data structures and support tuple parameters as the query range.

This commit is contained in:
Revone 2024-11-23 22:49:36 +13:00
parent 5077c0d291
commit 4298ac658b
3 changed files with 51 additions and 3 deletions

View file

@ -1,14 +1,20 @@
import { isComparable } from '../utils';
export enum DFSOperation {
VISIT = 0,
PROCESS = 1
}
export class Range<K> {
constructor(
public low: K,
public high: K,
public includeLow: boolean = true,
public includeHigh: boolean = true
) {}
) {
if (!(isComparable(low) && isComparable(high))) throw new RangeError('low or high is not comparable');
if (low > high) throw new RangeError('low must be less than or equal to high');
}
// Determine whether a key is within the range
isInRange(key: K, comparator: (a: K, b: K) => number): boolean {

View file

@ -609,6 +609,41 @@ export class BST<
return ans;
}
/**
* Time Complexity: O(log n)
* Space Complexity: O(n)
*
* The `rangeSearch` function searches for nodes within a specified range in a binary search tree.
* @param {Range<K> | [K, K]} range - The `range` parameter in the `rangeSearch` function can be
* either a `Range` object or an array of two elements representing the range boundaries.
* @param [onlyOne=false] - The `onlyOne` parameter is a boolean flag that indicates whether you want
* to stop the search after finding the first matching node within the specified range. If `onlyOne`
* is set to `true`, the search will return as soon as a single matching node is found. If `onlyOne`
* @param {C} callback - The `callback` parameter in the `rangeSearch` function is a callback
* function that is used to process each node that is found within the specified range during the
* search operation. It is of type `NodeCallback<NODE>`, where `NODE` is the type of nodes in the
* data structure.
* @param {BTNRep<K, V, NODE> | R} startNode - The `startNode` parameter in the `rangeSearch`
* function represents the node from which the search for nodes within the specified range will
* begin. It is the starting point for the range search operation.
* @param {IterationType} iterationType - The `iterationType` parameter in the `rangeSearch` function
* is used to specify the type of iteration to be performed during the search operation. It has a
* default value of `this.iterationType`, which suggests that it is likely a property of the class or
* object that the `rangeSearch`
* @returns The `rangeSearch` function is returning the result of calling the `search` method with
* the specified parameters.
*/
rangeSearch<C extends NodeCallback<NODE>>(
range: Range<K> | [K, K],
onlyOne = false,
callback: C = this._DEFAULT_NODE_CALLBACK as C,
startNode: BTNRep<K, V, NODE> | R = this._root,
iterationType: IterationType = this.iterationType
) {
const searchRange: Range<K> = range instanceof Range ? range : new Range(range[0], range[1]);
return this.search(searchRange, onlyOne, callback, startNode, iterationType);
}
/**
* Time Complexity: O(log n)
* Space Complexity: O(1)

View file

@ -489,6 +489,13 @@ describe('BST operations test', () => {
expect(treeMap.getNode(1)?.value).toBe(undefined);
expect(treeMap.get(1)).toBe('b');
});
it('should search in range', () => {
const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
expect(bst.rangeSearch([4, 12])).toEqual([10, 12, 5, 7]);
expect(() => bst.rangeSearch([12, 4])).toThrow('low must be less than or equal to high');
expect(bst.rangeSearch([12, 12])).toEqual([12]);
});
});
describe('BST operations test recursively', () => {
@ -1552,9 +1559,9 @@ describe('classic use', () => {
it('@example Find elements in a range', () => {
const bst = new BST<number>([10, 5, 15, 3, 7, 12, 18]);
expect(bst.search(new Range(5, 10))).toEqual([10, 5, 7]);
expect(bst.search(new Range(4, 12))).toEqual([10, 12, 5, 7]);
expect(bst.rangeSearch([4, 12], false, node => node.key.toString())).toEqual(['10', '12', '5', '7']);
expect(bst.search(new Range(4, 12, true, false))).toEqual([10, 5, 7]);
expect(bst.search(new Range(15, 20))).toEqual([15, 18]);
expect(bst.rangeSearch([15, 20])).toEqual([15, 18]);
expect(bst.search(new Range(15, 20, false))).toEqual([18]);
});