Skip to content

Commit

Permalink
fix: Adjust type safety for the map method of all binary trees, ensur…
Browse files Browse the repository at this point in the history
…ing it no longer returns the TREE type to its parent class and limiting Node type nesting to a maximum of 10 levels. Fix the issue with RedBlackTree objects being incorrectly compared when used as keys. Rename extractComparable to specificComparable. Correct the order of key and value in callback functions for the map and filter methods.
  • Loading branch information
zrwusa committed Nov 24, 2024
1 parent 1494ffa commit 1a1ea21
Show file tree
Hide file tree
Showing 32 changed files with 842 additions and 491 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)

## [v1.53.7](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)
## [v1.53.8](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming)

### Changes

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@

- Make your pull requests to be **specific** and **focused**. Instead of
contributing "several data structures" all at once contribute them all
one by one separately (i.e. one pull request for "RBTree", another one
one by one separately (i.e. one pull request for "RedBlackTree", another one
for "AATree" and so on).
- Modify **README.md** for each of the data structure **with explanations** of
the algorithm and **with links** to further readings.
Expand Down
52 changes: 26 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-structure-typed",
"version": "1.53.8",
"version": "1.53.9",
"description": "Javascript Data Structure. Heap, Binary Tree, Red Black Tree, Linked List, Deque, Trie, HashMap, Directed Graph, Undirected Graph, Binary Search Tree(BST), AVL Tree, Priority Queue, Graph, Queue, Tree Multiset, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue, Stack. Benchmark compared with C++ STL. API aligned with ES6 and Java.util. Usability is comparable to Python",
"main": "dist/cjs/index.js",
"module": "dist/mjs/index.js",
Expand Down Expand Up @@ -70,11 +70,11 @@
"@typescript-eslint/eslint-plugin": "^8.12.1",
"@typescript-eslint/parser": "^8.12.1",
"auto-changelog": "^2.5.0",
"avl-tree-typed": "^1.53.6",
"avl-tree-typed": "^1.53.7",
"benchmark": "^2.1.4",
"binary-tree-typed": "^1.53.6",
"bst-typed": "^1.53.6",
"data-structure-typed": "^1.53.6",
"binary-tree-typed": "^1.53.7",
"bst-typed": "^1.53.7",
"data-structure-typed": "^1.53.7",
"dependency-cruiser": "^16.5.0",
"doctoc": "^2.2.1",
"eslint": "^9.13.0",
Expand All @@ -83,7 +83,7 @@
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.31.0",
"fast-glob": "^3.3.2",
"heap-typed": "^1.53.6",
"heap-typed": "^1.53.7",
"istanbul-badges-readme": "^1.9.0",
"jest": "^29.7.0",
"js-sdsl": "^4.4.2",
Expand Down
135 changes: 81 additions & 54 deletions src/data-structures/binary-tree/avl-tree-multi-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @license MIT License
*/
import type {
AVLTreeMultiMapNested,
AVLTreeMultiMapNodeNested,
AVLTreeMultiMapOptions,
BinaryTreeDeleteResult,
BSTNOptKeyOrNode,
BTNRep,
EntryCallback,
IterationType
} from '../../types';
import { IBinaryTree } from '../../interfaces';
Expand Down Expand Up @@ -64,17 +64,10 @@ export class AVLTreeMultiMap<
K = any,
V = any,
R = object,
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>,
TREE extends AVLTreeMultiMap<K, V, R, NODE, TREE> = AVLTreeMultiMap<
K,
V,
R,
NODE,
AVLTreeMultiMapNested<K, V, R, NODE>
>
NODE extends AVLTreeMultiMapNode<K, V, NODE> = AVLTreeMultiMapNode<K, V, AVLTreeMultiMapNodeNested<K, V>>
>
extends AVLTree<K, V, R, NODE, TREE>
implements IBinaryTree<K, V, R, NODE, TREE>
extends AVLTree<K, V, R, NODE>
implements IBinaryTree<K, V, R, NODE>
{
/**
* The constructor initializes a new AVLTreeMultiMap object with optional initial elements.
Expand Down Expand Up @@ -139,15 +132,16 @@ export class AVLTreeMultiMap<
* @returns a new instance of the AVLTreeMultiMap class, with the specified options, as a TREE
* object.
*/
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>): TREE {
return new AVLTreeMultiMap<K, V, R, NODE, TREE>([], {
// @ts-ignore
override createTree(options?: AVLTreeMultiMapOptions<K, V, R>) {
return new AVLTreeMultiMap<K, V, R, NODE>([], {
iterationType: this.iterationType,
isMapMode: this._isMapMode,
extractComparable: this._extractComparable,
specifyComparable: this._specifyComparable,
toEntryFn: this._toEntryFn,
isReverse: this._isReverse,
...options
}) as TREE;
});
}

/**
Expand All @@ -161,44 +155,6 @@ export class AVLTreeMultiMap<
return keyNodeEntryOrRaw instanceof AVLTreeMultiMapNode;
}

/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<K, V, NODE>`.
* @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`.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];

if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue, count), finalValue];
}

if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, count), finalValue];
}

if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, count), value];

return [undefined, undefined];
}

/**
* Time Complexity: O(log n)
* Space Complexity: O(1)
Expand Down Expand Up @@ -374,14 +330,85 @@ export class AVLTreeMultiMap<
* The function overrides the clone method to create a deep copy of a tree object.
* @returns The `clone()` method is returning a cloned instance of the `TREE` object.
*/
override clone(): TREE {
// @ts-ignore
override clone() {
const cloned = this.createTree();
if (this._isMapMode) this.bfs(node => cloned.add(node.key, undefined, node.count));
else this.bfs(node => cloned.add(node.key, node.value, node.count));
if (this._isMapMode) cloned._store = this._store;
return cloned;
}

/**
* The `map` function in TypeScript overrides the default behavior to create a new AVLTreeMultiMap
* with modified entries based on a provided callback.
* @param callback - The `callback` parameter is a function that will be called for each entry in the
* AVLTreeMultiMap. It takes four arguments:
* @param [options] - The `options` parameter in the `override map` function is of type
* `AVLTreeMultiMapOptions<MK, MV, MR>`. This parameter allows you to provide additional
* configuration options when creating a new `AVLTreeMultiMap` instance within the `map` function.
* These options
* @param {any} [thisArg] - The `thisArg` parameter in the `override map` function is used to specify
* the value of `this` when executing the `callback` function. It allows you to set the context
* (value of `this`) for the callback function. This can be useful when you want to access properties
* or
* @returns The `map` method is returning a new `AVLTreeMultiMap` instance with the entries
* transformed by the provided `callback` function. Each entry in the original tree is passed to the
* `callback` function along with the index and the original tree itself. The transformed entries are
* then added to the new `AVLTreeMultiMap` instance, which is returned at the end.
*/
// @ts-ignore
override map<MK, MV, MR>(
callback: EntryCallback<K, V | undefined, [MK, MV]>,
options?: AVLTreeMultiMapOptions<MK, MV, MR>,
thisArg?: any
) {
const newTree = new AVLTreeMultiMap<MK, MV, MR>([], options);
let index = 0;
for (const [key, value] of this) {
newTree.add(callback.call(thisArg, key, value, index++, this));
}
return newTree;
}

/**
* The function `keyValueNodeEntryRawToNodeAndValue` converts a key, value, entry, or raw element into
* a node object.
* @param {BTNRep<K, V, NODE> | R} keyNodeEntryOrRaw - The
* `keyNodeEntryOrRaw` parameter can be of type `R` or `BTNRep<K, V, NODE>`.
* @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`.
* @param [count=1] - The `count` parameter is an optional parameter that specifies the number of
* times the key-value pair should be added to the data structure. If not provided, it defaults to 1.
* @returns either a NODE object or undefined.
*/
protected override _keyValueNodeEntryRawToNodeAndValue(
keyNodeEntryOrRaw: BTNRep<K, V, NODE> | R,
value?: V,
count = 1
): [NODE | undefined, V | undefined] {
if (keyNodeEntryOrRaw === undefined || keyNodeEntryOrRaw === null) return [undefined, undefined];
if (this.isNode(keyNodeEntryOrRaw)) return [keyNodeEntryOrRaw, value];

if (this.isEntry(keyNodeEntryOrRaw)) {
const [key, entryValue] = keyNodeEntryOrRaw;
if (key === undefined || key === null) return [undefined, undefined];
const finalValue = value ?? entryValue;
return [this.createNode(key, finalValue, count), finalValue];
}

if (this.isRaw(keyNodeEntryOrRaw)) {
const [key, entryValue] = this._toEntryFn!(keyNodeEntryOrRaw);
const finalValue = value ?? entryValue;
if (this.isKey(key)) return [this.createNode(key, finalValue, count), finalValue];
}

if (this.isKey(keyNodeEntryOrRaw)) return [this.createNode(keyNodeEntryOrRaw, value, count), value];

return [undefined, undefined];
}

/**
* Time Complexity: O(1)
* Space Complexity: O(1)
Expand Down
Loading

0 comments on commit 1a1ea21

Please sign in to comment.