Skip to content

Commit

Permalink
style: Utilize the built-in _dfs method across all binary tree data s…
Browse files Browse the repository at this point in the history
…tructures to optimize the search method.

feat: The search and rangeSearch methods in binary trees now default to in-order traversal for producing ordered results.
docs: Add sample code for AVLTree. Explicitly document method parameter types for all binary tree data structures.
  • Loading branch information
zrwusa committed Dec 2, 2024
1 parent b759eec commit a008a33
Show file tree
Hide file tree
Showing 16 changed files with 875 additions and 654 deletions.
53 changes: 30 additions & 23 deletions src/data-structures/binary-tree/avl-tree-counter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import type {
AVLTreeCounterOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
EntryCallback,
IterationType,
OptNodeOrNull
IterationType
} from '../../types';
import { IBinaryTree } from '../../interfaces';
import { AVLTree, AVLTreeNode } from './avl-tree';

export class AVLTreeCounterNode<K = any, V = any> extends AVLTreeNode<K, V> {
override parent?: AVLTreeCounterNode<K, V> = undefined;

/**
* The constructor function initializes a BinaryTreeNode object with a key, value, and count.
* @param {K} key - The `key` parameter is of type `K` and represents the unique identifier
Expand All @@ -33,28 +33,26 @@ export class AVLTreeCounterNode<K = any, V = any> extends AVLTreeNode<K, V> {
this.count = count;
}

override parent?: AVLTreeCounterNode<K, V> = undefined;

override _left?: OptNodeOrNull<AVLTreeCounterNode<K, V>> = undefined;
override _left?: AVLTreeCounterNode<K, V> | null | undefined = undefined;

override get left(): OptNodeOrNull<AVLTreeCounterNode<K, V>> {
override get left(): AVLTreeCounterNode<K, V> | null | undefined {
return this._left;
}

override set left(v: OptNodeOrNull<AVLTreeCounterNode<K, V>>) {
override set left(v: AVLTreeCounterNode<K, V> | null | undefined) {
if (v) {
v.parent = this;
}
this._left = v;
}

override _right?: OptNodeOrNull<AVLTreeCounterNode<K, V>> = undefined;
override _right?: AVLTreeCounterNode<K, V> | null | undefined = undefined;

override get right(): OptNodeOrNull<AVLTreeCounterNode<K, V>> {
override get right(): AVLTreeCounterNode<K, V> | null | undefined {
return this._right;
}

override set right(v: OptNodeOrNull<AVLTreeCounterNode<K, V>>) {
override set right(v: AVLTreeCounterNode<K, V> | null | undefined) {
if (v) {
v.parent = this;
}
Expand All @@ -78,7 +76,9 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
* `compareValues` functions to define custom comparison logic for keys and values, respectively.
*/
constructor(
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V, AVLTreeCounterNode<K, V>> | R> = [],
keysNodesEntriesOrRaws: Iterable<
K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined | R
> = [],
options?: AVLTreeCounterOptions<K, V, R>
) {
super([], options);
Expand Down Expand Up @@ -145,12 +145,14 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR

/**
* The function checks if the input is an instance of AVLTreeCounterNode.
* @param {BTNRep<K, V, AVLTreeCounterNode<K, V>>} keyNodeOrEntry - The parameter
* `keyNodeOrEntry` can be of type `R` or `BTNRep<K, V, AVLTreeCounterNode<K, V>>`.
* @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The parameter
* `keyNodeOrEntry` can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.
* @returns a boolean value indicating whether the input parameter `keyNodeOrEntry` is
* an instance of the `AVLTreeCounterNode` class.
*/
override isNode(keyNodeOrEntry: BTNRep<K, V, AVLTreeCounterNode<K, V>>): keyNodeOrEntry is AVLTreeCounterNode<K, V> {
override isNode(
keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined
): keyNodeOrEntry is AVLTreeCounterNode<K, V> {
return keyNodeOrEntry instanceof AVLTreeCounterNode;
}

Expand All @@ -160,9 +162,9 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
*
* The function overrides the add method of a TypeScript class to add a new node to a data structure
* and update the count.
* @param {BTNRep<K, V, AVLTreeCounterNode<K, V>>} keyNodeOrEntry - The
* @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The
* `keyNodeOrEntry` parameter can accept a value of type `R`, which can be any type. It
* can also accept a value of type `BTNRep<K, V, AVLTreeCounterNode<K, V>>`, which represents a key, node,
* can also accept a value of type `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`, which represents a key, node,
* entry, or raw element
* @param {V} [value] - The `value` parameter represents the value associated with the key in the
* data structure. It is an optional parameter, so it can be omitted if not needed.
Expand All @@ -171,7 +173,11 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
* be added once. However, you can specify a different value for `count` if you want to add
* @returns a boolean value.
*/
override add(keyNodeOrEntry: BTNRep<K, V, AVLTreeCounterNode<K, V>>, value?: V, count = 1): boolean {
override add(
keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
value?: V,
count = 1
): boolean {
const [newNode, newValue] = this._keyValueNodeOrEntryToNodeAndValue(keyNodeOrEntry, value, count);
if (newNode === undefined) return false;

Expand All @@ -189,7 +195,7 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
*
* The function overrides the delete method in a binary tree data structure, handling deletion of
* nodes and maintaining balance in the tree.
* @param {BTNRep<K, V, AVLTreeCounterNode<K, V>>} keyNodeOrEntry - The `predicate`
* @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The `predicate`
* parameter in the `delete` method is used to specify the condition for deleting a node from the
* binary tree. It can be a key, node, or entry that determines which
* node(s) should be deleted.
Expand All @@ -203,7 +209,7 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
* deleted node and whether balancing is needed in the tree.
*/
override delete(
keyNodeOrEntry: BTNRep<K, V, AVLTreeCounterNode<K, V>>,
keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
ignoreCount = false
): BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] {
const deletedResult: BinaryTreeDeleteResult<AVLTreeCounterNode<K, V>>[] = [];
Expand Down Expand Up @@ -276,6 +282,7 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
/**
* Time Complexity: O(n log n)
* Space Complexity: O(log n)
*
* The `perfectlyBalance` function takes a sorted array of nodes and builds a balanced binary search
* tree using either a recursive or iterative approach.
* @param {IterationType} iterationType - The `iterationType` parameter is an optional parameter that
Expand Down Expand Up @@ -374,8 +381,8 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, AVLTreeCounterNode<K, V>>} keyNodeOrEntry - The
* `keyNodeOrEntry` parameter can be of type `R` or `BTNRep<K, V, AVLTreeCounterNode<K, V>>`.
* @param {K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined} keyNodeOrEntry - The
* `keyNodeOrEntry` parameter can be of type `R` or `K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined`.
* @param {V} [value] - The `value` parameter is an optional value that can be passed to the
* `override` function. It represents the value associated with the key in the data structure. If no
* value is provided, it will default to `undefined`.
Expand All @@ -384,7 +391,7 @@ export class AVLTreeCounter<K = any, V = any, R = object, MK = any, MV = any, MR
* @returns either a AVLTreeCounterNode<K, V> object or undefined.
*/
protected override _keyValueNodeOrEntryToNodeAndValue(
keyNodeOrEntry: BTNRep<K, V, AVLTreeCounterNode<K, V>>,
keyNodeOrEntry: K | AVLTreeCounterNode<K, V> | [K | null | undefined, V | undefined] | null | undefined,
value?: V,
count = 1
): [AVLTreeCounterNode<K, V> | undefined, V | undefined] {
Expand Down
40 changes: 25 additions & 15 deletions src/data-structures/binary-tree/avl-tree-multi-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
* @copyright Copyright (c) 2022 Pablo Zeng <zrwusa@gmail.com>
* @license MIT License
*/
import { AVLTreeMultiMapOptions, BTNOptKeyOrNull, BTNRep, OptNodeOrNull } from '../../types';
import { AVLTreeMultiMapOptions, BTNOptKeyOrNull } from '../../types';
import { AVLTree, AVLTreeNode } from './avl-tree';
import { IBinaryTree } from '../../interfaces';

export class AVLTreeMultiMapNode<K = any, V = any> extends AVLTreeNode<K, V[]> {
override parent?: AVLTreeMultiMapNode<K, V> = undefined;

/**
* This TypeScript constructor initializes an object with a key of type K and an array of values of
* type V.
Expand All @@ -23,28 +25,26 @@ export class AVLTreeMultiMapNode<K = any, V = any> extends AVLTreeNode<K, V[]> {
super(key, value);
}

override parent?: AVLTreeMultiMapNode<K, V> = undefined;

override _left?: OptNodeOrNull<AVLTreeMultiMapNode<K, V>> = undefined;
override _left?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;

override get left(): OptNodeOrNull<AVLTreeMultiMapNode<K, V>> {
override get left(): AVLTreeMultiMapNode<K, V> | null | undefined {
return this._left;
}

override set left(v: OptNodeOrNull<AVLTreeMultiMapNode<K, V>>) {
override set left(v: AVLTreeMultiMapNode<K, V> | null | undefined) {
if (v) {
v.parent = this;
}
this._left = v;
}

override _right?: OptNodeOrNull<AVLTreeMultiMapNode<K, V>> = undefined;
override _right?: AVLTreeMultiMapNode<K, V> | null | undefined = undefined;

override get right(): OptNodeOrNull<AVLTreeMultiMapNode<K, V>> {
override get right(): AVLTreeMultiMapNode<K, V> | null | undefined {
return this._right;
}

override set right(v: OptNodeOrNull<AVLTreeMultiMapNode<K, V>>) {
override set right(v: AVLTreeMultiMapNode<K, V> | null | undefined) {
if (v) {
v.parent = this;
}
Expand All @@ -71,7 +71,9 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
* additional options for configuring the AVLTreeMultiMap instance.
*/
constructor(
keysNodesEntriesOrRaws: Iterable<BTNRep<K, V[], AVLTreeMultiMapNode<K, V>> | R> = [],
keysNodesEntriesOrRaws: Iterable<
K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | R
> = [],
options?: AVLTreeMultiMapOptions<K, V[], R>
) {
super([], { ...options, isMapMode: true });
Expand Down Expand Up @@ -117,7 +119,9 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
return new AVLTreeMultiMapNode<K, V>(key, []);
}

override add(node: BTNRep<K, V[], AVLTreeMultiMapNode<K, V>>): boolean;
override add(
node: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined
): boolean;

override add(key: K, value: V): boolean;

Expand All @@ -127,7 +131,7 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
*
* The function `add` in TypeScript overrides the superclass method to add key-value pairs to an AVL
* tree multi-map.
* @param {BTNRep<K, V[], AVLTreeMultiMapNode<K, V>> | K} keyNodeOrEntry - The `keyNodeOrEntry`
* @param {K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K} keyNodeOrEntry - The `keyNodeOrEntry`
* parameter in the `override add` method can be either a key-value pair entry or just a key. If it
* is a key-value pair entry, it will be in the format `[key, values]`, where `key` is the key and
* `values`
Expand All @@ -137,7 +141,10 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
* @returns The `override add` method is returning a boolean value, which indicates whether the
* addition operation was successful or not.
*/
override add(keyNodeOrEntry: BTNRep<K, V[], AVLTreeMultiMapNode<K, V>> | K, value?: V): boolean {
override add(
keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,
value?: V
): boolean {
if (this.isRealNode(keyNodeOrEntry)) return super.add(keyNodeOrEntry);

const _commonAdd = (key?: BTNOptKeyOrNull<K>, values?: V[]) => {
Expand Down Expand Up @@ -180,7 +187,7 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
*
* The function `deleteValue` removes a specific value from a key in an AVLTreeMultiMap data
* structure and deletes the entire node if no values are left for that key.
* @param {BTNRep<K, V[], AVLTreeMultiMapNode<K, V>> | K} keyNodeOrEntry - The `keyNodeOrEntry`
* @param {K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K} keyNodeOrEntry - The `keyNodeOrEntry`
* parameter in the `deleteValue` function can be either a `BTNRep` object representing a key-value
* pair in the AVLTreeMultiMapNode, or just the key itself.
* @param {V} value - The `value` parameter in the `deleteValue` function represents the specific
Expand All @@ -191,7 +198,10 @@ export class AVLTreeMultiMap<K = any, V = any, R = object, MK = any, MV = any, M
* `value` was successfully deleted from the array of values associated with the `keyNodeOrEntry`. If
* the value was not found in the array, it returns `false`.
*/
deleteValue(keyNodeOrEntry: BTNRep<K, V[], AVLTreeMultiMapNode<K, V>> | K, value: V): boolean {
deleteValue(
keyNodeOrEntry: K | AVLTreeMultiMapNode<K, V> | [K | null | undefined, V[] | undefined] | null | undefined | K,
value: V
): boolean {
const values = this.get(keyNodeOrEntry);
if (Array.isArray(values)) {
const index = values.indexOf(value);
Expand Down
Loading

0 comments on commit a008a33

Please sign in to comment.