From 4298ac658b1d8bbc6ad51e1a54beb0576cb7ad9a Mon Sep 17 00:00:00 2001 From: Revone Date: Sat, 23 Nov 2024 22:49:36 +1300 Subject: [PATCH] feat: Add a rangeSearch method to binary search tree data structures and support tuple parameters as the query range. --- src/common/index.ts | 8 ++++- src/data-structures/binary-tree/bst.ts | 35 +++++++++++++++++++ .../data-structures/binary-tree/bst.test.ts | 11 ++++-- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/common/index.ts b/src/common/index.ts index dc88776..2572c9a 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,14 +1,20 @@ +import { isComparable } from '../utils'; + export enum DFSOperation { VISIT = 0, PROCESS = 1 } + export class Range { 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 { diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 813f153..d9a52e9 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -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]} 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`, where `NODE` is the type of nodes in the + * data structure. + * @param {BTNRep | 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>( + range: Range | [K, K], + onlyOne = false, + callback: C = this._DEFAULT_NODE_CALLBACK as C, + startNode: BTNRep | R = this._root, + iterationType: IterationType = this.iterationType + ) { + const searchRange: Range = 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) diff --git a/test/unit/data-structures/binary-tree/bst.test.ts b/test/unit/data-structures/binary-tree/bst.test.ts index 8350be8..ef42bde 100644 --- a/test/unit/data-structures/binary-tree/bst.test.ts +++ b/test/unit/data-structures/binary-tree/bst.test.ts @@ -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([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([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]); });