Rework the add, addMany, and fill methods of AbstractBinaryTree. Refactor the AddMany method of TreeMultiset. Fix the bug in TreeMultiset where all Node counts become 1 after calling the perfectBalance method. Remove the unnecessary configuration of autoIncrementId.

This commit is contained in:
Revone 2023-08-31 20:02:31 +08:00
parent bd71edc536
commit 2d1010b352
15 changed files with 456 additions and 283 deletions

228
package-lock.json generated
View file

@ -1,27 +1,43 @@
{
"name": "data-structure-typed",
"version": "1.19.5",
"version": "1.19.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "data-structure-typed",
"version": "1.19.5",
"version": "1.19.7",
"license": "MIT",
"dependencies": {
"avl-tree-typed": "^1.19.5",
"bst-typed": "^1.19.5",
"heap-typed": "^1.19.5",
"zod": "^3.22.2"
},
"devDependencies": {
"@types/jest": "^29.5.3",
"@types/node": "^20.4.9",
"avl-tree-typed": "^1.19.7",
"binary-tree-typed": "^1.19.7",
"bst-typed": "^1.19.7",
"dependency-cruiser": "^13.1.2",
"deque-typed": "^1.19.7",
"directed-graph-typed": "^1.19.7",
"doubly-linked-list-typed": "^1.19.7",
"graph-typed": "^1.19.7",
"heap-typed": "^1.19.7",
"jest": "^29.6.2",
"linked-list-typed": "^1.19.7",
"max-heap-typed": "^1.19.7",
"max-priority-queue-typed": "^1.19.7",
"min-heap-typed": "^1.19.7",
"min-priority-queue-typed": "^1.19.7",
"priority-queue-typed": "^1.19.7",
"singly-linked-list-typed": "^1.19.7",
"stack-typed": "^1.19.7",
"tree-multiset-typed": "^1.19.7",
"trie-typed": "^1.19.7",
"ts-jest": "^29.1.1",
"typedoc": "^0.24.8",
"typescript": "^4.9.5"
"typescript": "^4.9.5",
"undirected-graph-typed": "^1.19.7"
}
},
"node_modules/@ampproject/remapping": {
@ -1627,11 +1643,12 @@
}
},
"node_modules/avl-tree-typed": {
"version": "1.19.45",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.19.45.tgz",
"integrity": "sha512-/uluq7j+c5iTmcVzHHvuMKWdoIJ9ZqSfDgRXkPIqBHXxOEr05jxfwt1IRgdxJhsv3gOv4/mRzKJKfwNqjKv1Qg==",
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.19.7.tgz",
"integrity": "sha512-aoOVWmf8egxEc8qclllznUAWJrqzHtFPiSX4flM6G4NnxOOxsDAXGTU8gpo0tzfn3dM8/J6oBkm2OsV7HeXsoQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.4",
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
@ -1806,6 +1823,16 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/binary-tree-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.19.7.tgz",
"integrity": "sha512-oW7fa2zWAxBcsAD8Wdl4+//L02W+pocggPNEg5nhL/tOl1EUcY6aoVJ2hmrJg9C1VclRvGpVV57VFyEMfCxpXQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -1881,11 +1908,12 @@
}
},
"node_modules/bst-typed": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.19.5.tgz",
"integrity": "sha512-xvW7t2v6G6YA3pyLTAnxTrIeOy+Lpuwi9Sr/lVnif7sJhAh4qutUu9PQZgttTfqdySGfBHux4N7bOCj5/l17KQ==",
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.19.7.tgz",
"integrity": "sha512-ngXIfUtNJ22BNWnxo27x3sAgOCPXTcHk4jFdYaaoAqyxJKbUcmquNV0XRym0JfEAuscwSXr6+JtQMS5OFpNxDw==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.5",
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
@ -2147,12 +2175,14 @@
}
},
"node_modules/data-structure-typed": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.19.5.tgz",
"integrity": "sha512-Q6rn8ww6AN8es5FD49p1pRuka5TIH3bp/nb3LmsAuL0ChecskVf2V94iNk33aRQXnvQwN8R+4YBsEn2j1/xqQA==",
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.19.7.tgz",
"integrity": "sha512-01z8P6DDXy044GitWYxds7sQzAYS1USxVAQEl7v8gSSa4YG7nzg0ZhL/xyU3QjzFjn+XsJWCOaiNG8eMFr54HQ==",
"dev": true,
"dependencies": {
"avl-tree-typed": "^1.19.44",
"bst-typed": "^1.19.45",
"avl-tree-typed": "^1.19.6",
"bst-typed": "^1.19.6",
"heap-typed": "^1.19.6",
"zod": "^3.22.2"
}
},
@ -2160,6 +2190,7 @@
"version": "1.19.45",
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.19.45.tgz",
"integrity": "sha512-x/vLIaFDdgv4zcTVgpJmTwW6BanpPPM9eE/P8v72VE9eFgBEspDGOSJsd4Fel7fO8DF+MUqwksMreCln0ECy3g==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.4",
"zod": "^3.22.2"
@ -2250,6 +2281,16 @@
"node": "^16.14||>=18"
}
},
"node_modules/deque-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/deque-typed/-/deque-typed-1.19.7.tgz",
"integrity": "sha512-boNOe04x7q1AC1OIZumU81rwCd6t0wh4CUHH6eWFpibgJmjLQRCgWgqHoXpRX2z6k1nS16MsliCbexk/2YAkiQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/detect-newline": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
@ -2268,6 +2309,26 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/directed-graph-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/directed-graph-typed/-/directed-graph-typed-1.19.7.tgz",
"integrity": "sha512-mHoiatm3UpCZjBd/L33bnPHsKGR5WRslR5fiS9+dmmmcT8PDpBiHVtVrNLkEKNVFXrl9nTkwC0e08/elNhhaMg==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/doubly-linked-list-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/doubly-linked-list-typed/-/doubly-linked-list-typed-1.19.7.tgz",
"integrity": "sha512-N6/D0ET5siuQbsPVf6VuiYDnGXH6FUF/bJv6bwtX0Pse0+N8AVayd1mUUcuZT00tyMm3Tb4CxqKrqIuW195riQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@ -2603,6 +2664,16 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true
},
"node_modules/graph-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/graph-typed/-/graph-typed-1.19.7.tgz",
"integrity": "sha512-9vo//L6UAMR9NfvHNYgFzAMF4Jx6aBpA1fx+n1WVOdP4kpni1kNRVCJQ98c51zFtkEuZvRie9g4hkYqv598aSQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@ -2625,11 +2696,12 @@
}
},
"node_modules/heap-typed": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.19.5.tgz",
"integrity": "sha512-E7H53VmkgDIa1+sVqao2i/QcUE2k85ZYLAmknM9+2QMb9wjJOCaFNiPjuZJLb0J7q+4nrgGedF7kxGFZFa+gwQ==",
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.19.7.tgz",
"integrity": "sha512-837IoAkdgeoRWXam/RG/bYPnMyDORBiEPPV/Bs0NOj6sCVe9p81VjtkGYnz2DPgdFk5C/DEfriExuZiTqPsjhQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.5",
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
@ -4326,6 +4398,16 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
"node_modules/linked-list-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/linked-list-typed/-/linked-list-typed-1.19.7.tgz",
"integrity": "sha512-P68uY6aRX47Ett8zgHKK7tp6nBlAB86cXwqpREEgEv5ruk70HPH4M/7RO7LD0J6x8VJiTF0Ws3/ikBTHjPZjeg==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@ -4407,6 +4489,26 @@
"node": ">= 12"
}
},
"node_modules/max-heap-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/max-heap-typed/-/max-heap-typed-1.19.7.tgz",
"integrity": "sha512-iix1moDPx5bL784FfSv+6ocbme0etHMm3ezK8NKkixDp0gmTbHmzOA7lQ9EimFhVTUYs6W/PipO8BPdE0UxFnw==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/max-priority-queue-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/max-priority-queue-typed/-/max-priority-queue-typed-1.19.7.tgz",
"integrity": "sha512-qjGVxjoQYrk8O52WSkq0LwQ0EWAfOEzVQZ/LCX2tIRbePuw0HaDh7LQ4+Z3Pi5BXG6E/6JwJPljNNGoBvinFxQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -4435,6 +4537,26 @@
"node": ">=6"
}
},
"node_modules/min-heap-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/min-heap-typed/-/min-heap-typed-1.19.7.tgz",
"integrity": "sha512-CEbz/U1qRo14udGnc2AW6Zo83EZmQBP43KhG/dE7BM8Bbbq+QCD6M1JVpc349AbUgGpV8e75S4jPaS2nO/QbaQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/min-priority-queue-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/min-priority-queue-typed/-/min-priority-queue-typed-1.19.7.tgz",
"integrity": "sha512-he+5IOCkBAeES9v/v9zBLUQVL7BNopt2uegyYUZESRb9I12ii3jQNfzhK1tTejMtXzmkPbgrSLe7RbMXAeq8fw==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
@ -4717,6 +4839,16 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/priority-queue-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/priority-queue-typed/-/priority-queue-typed-1.19.7.tgz",
"integrity": "sha512-+ffaKPE8I09fKErdAZXevSO8fAvv9A5ADomAPBRa+LDyfsm3TrTRCXBWpt1KLlBI3DB2ZJczUsbrCfnDKDcqwg==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@ -4946,6 +5078,16 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/singly-linked-list-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/singly-linked-list-typed/-/singly-linked-list-typed-1.19.7.tgz",
"integrity": "sha512-iYik+sWJwInLIXVWlrKT52jfLP5iv7xZRA4eeaMhEwDJCa4Nb/BcTFAaWZeo8cELxCcDxP8w/vvDSsmePbftDQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -4986,6 +5128,16 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"node_modules/stack-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/stack-typed/-/stack-typed-1.19.7.tgz",
"integrity": "sha512-QlGwJ1GhgXynVDgRWQYmcTdVtt3457dd4ZywPp05aQOMw//H9au4FVm+VmZ0cW4nm7MNhTkjuf4oFjMz8hZSZQ==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/stack-utils": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@ -5289,6 +5441,26 @@
"node": ">=8.0"
}
},
"node_modules/tree-multiset-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/tree-multiset-typed/-/tree-multiset-typed-1.19.7.tgz",
"integrity": "sha512-TqX9ALuiSNbTj22NxCjrHLfCbwzl4talhixXjw7+8FbgCGJEatJgqqs4/5/kMxo6dK5KH+Wwu9aA0yxYadX67w==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/trie-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/trie-typed/-/trie-typed-1.19.7.tgz",
"integrity": "sha512-/IIosdfQKEaLyK4VQ/pCEX4Ya02d+wylrhLJNxW/wA2JbMhSRCmQoVkvZhyFX328CnQE1q9SIovD7g3BHbzbTA==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/ts-jest": {
"version": "29.1.1",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
@ -5473,6 +5645,16 @@
"node": ">=4.2.0"
}
},
"node_modules/undirected-graph-typed": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/undirected-graph-typed/-/undirected-graph-typed-1.19.7.tgz",
"integrity": "sha512-9+lFDIy/aUO8rpudzRYQI51n+X9xGdMevId2Cs70oDQoxX2dDGgm1iN1SG5hHl3Bb3YpjLh9aJ40WVke+HGt5Q==",
"dev": true,
"dependencies": {
"data-structure-typed": "^1.19.7",
"zod": "^3.22.2"
}
},
"node_modules/update-browserslist-db": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz",

View file

@ -6,6 +6,7 @@
"scripts": {
"build": "rm -rf dist && npx tsc",
"test": "jest",
"update:test-deps": "npm i avl-tree-typed binary-tree-typed bst-typed deque-typed directed-graph-typed doubly-linked-list-typed graph-typed heap-typed linked-list-typed max-heap-typed max-priority-queue-typed min-heap-typed min-priority-queue-typed priority-queue-typed singly-linked-list-typed stack-typed tree-multiset-typed trie-typed undirected-graph-typed --save-dev",
"build:docs": "typedoc --out docs ./src",
"deps:check": "dependency-cruiser src",
"build:publish": "npm run test && npm run build && npm run build:docs && npm publish"
@ -58,16 +59,32 @@
"devDependencies": {
"@types/jest": "^29.5.3",
"@types/node": "^20.4.9",
"avl-tree-typed": "^1.19.7",
"binary-tree-typed": "^1.19.7",
"bst-typed": "^1.19.7",
"dependency-cruiser": "^13.1.2",
"deque-typed": "^1.19.7",
"directed-graph-typed": "^1.19.7",
"doubly-linked-list-typed": "^1.19.7",
"graph-typed": "^1.19.7",
"heap-typed": "^1.19.7",
"jest": "^29.6.2",
"linked-list-typed": "^1.19.7",
"max-heap-typed": "^1.19.7",
"max-priority-queue-typed": "^1.19.7",
"min-heap-typed": "^1.19.7",
"min-priority-queue-typed": "^1.19.7",
"priority-queue-typed": "^1.19.7",
"singly-linked-list-typed": "^1.19.7",
"stack-typed": "^1.19.7",
"tree-multiset-typed": "^1.19.7",
"trie-typed": "^1.19.7",
"ts-jest": "^29.1.1",
"typedoc": "^0.24.8",
"typescript": "^4.9.5"
"typescript": "^4.9.5",
"undirected-graph-typed": "^1.19.7"
},
"dependencies": {
"avl-tree-typed": "^1.19.6",
"bst-typed": "^1.19.6",
"heap-typed": "^1.19.6",
"zod": "^3.22.2"
}
}

View file

@ -6,7 +6,7 @@
* @license MIT License
*/
import {ObjectWithNumberId, trampoline} from '../../utils';
import {trampoline} from '../../utils';
import type {
AbstractBinaryTreeNodeNested,
AbstractBinaryTreeNodeProperties,
@ -22,7 +22,6 @@ import {IAbstractBinaryTree, IAbstractBinaryTreeNode} from '../interfaces';
export abstract class AbstractBinaryTreeNode<T = any, NEIGHBOR extends AbstractBinaryTreeNode<T, NEIGHBOR> = AbstractBinaryTreeNodeNested<T>> implements IAbstractBinaryTreeNode<T, NEIGHBOR> {
/**
* The constructor function initializes a BinaryTreeNode object with an id and an optional value.
* @param {BinaryTreeNodeId} id - The `id` parameter is of type `BinaryTreeNodeId` and represents the unique identifier
@ -30,7 +29,7 @@ export abstract class AbstractBinaryTreeNode<T = any, NEIGHBOR extends AbstractB
* @param {T} [val] - The "val" parameter is an optional parameter of type T. It represents the value that will be
* stored in the binary tree node. If no value is provided, it will be set to undefined.
*/
constructor(id: BinaryTreeNodeId, val?: T) {
protected constructor(id: BinaryTreeNodeId, val?: T) {
this._id = id;
this._val = val;
}
@ -144,11 +143,9 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
if (options !== undefined) {
const {
loopType = LoopType.ITERATIVE,
autoIncrementId = false,
isMergeDuplicatedVal = true
} = options;
this._isMergeDuplicatedVal = isMergeDuplicatedVal;
this._autoIncrementId = autoIncrementId;
this._loopType = loopType;
}
}
@ -171,12 +168,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
return this._loopType;
}
private _autoIncrementId: boolean = false;
get autoIncrementId(): boolean {
return this._autoIncrementId;
}
private _maxId: number = -1;
get maxId(): number {
@ -268,15 +259,12 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
}
/**
* The `add` function adds a new node to a binary tree, updating the value of an existing node if it already exists.
* @param {BinaryTreeNodeId} id - The `id` parameter is the identifier of the binary tree node that you want to add.
* @param [val] - The `val` parameter is an optional value that can be assigned to the node being added. If no value is
* provided, the default value will be the same as the `id` parameter.
* @param {number} [count] - The `count` parameter is an optional number that represents the number of times the value
* should be added to the binary tree. If not provided, the default value is `undefined`.
* @returns The function `add` returns either a `BinaryTreeNode` object (`N`), `null`, or `undefined`.
* The `add` function adds a new node to a binary tree, either by updating an existing node or inserting a new node.
* @param {BinaryTreeNodeId | N} id - The `id` parameter can be either a `BinaryTreeNodeId` or `N`.
* @param [val] - The `val` parameter is an optional value that can be assigned to the node being added.
* @returns The function `add` returns either the inserted node (`N`), `null`, or `undefined`.
*/
add(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null | undefined {
add(id: BinaryTreeNodeId | N | null, val?: N['val']): N | null | undefined {
const _bfs = (root: N, newNode: N | null): N | undefined | null => {
const queue: Array<N | null> = [root];
while (queue.length > 0) {
@ -292,21 +280,30 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
};
let inserted: N | null | undefined;
const needInsert = val !== null ? this.createNode(id, val) : null;
const existNode = val !== null ? this.get(id, 'id') : null;
let needInsert;
if (id === null) {
needInsert = null;
} else if (typeof id === 'number') {
needInsert = this.createNode(id, val);
} else if (id instanceof AbstractBinaryTreeNode) {
needInsert = id;
} else {
return;
}
const existNode = id ? this.get(id, 'id') : undefined;
if (this.root) {
if (existNode) {
existNode.val = val ?? id;
if (needInsert !== null) {
inserted = existNode;
}
existNode.val = val;
inserted = existNode;
} else {
inserted = _bfs(this.root, needInsert);
}
} else {
this._setRoot(val !== null ? this.createNode(id, val) : null);
this._setRoot(needInsert);
if (needInsert !== null) {
this._setSize(1);
} else {
this._setSize(0);
}
inserted = this.root;
}
@ -352,78 +349,60 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
}
/**
* The `addMany` function adds multiple nodes to a binary tree and returns an array of the inserted nodes or
* The `addMany` function adds multiple nodes to a tree data structure and returns an array of the inserted nodes or
* null/undefined values.
* @param {N[] | Array<N['val']>} data - The `data` parameter can be either an array of `N` objects or an array of
* `N['val']` values.
* @returns The function `addMany` returns an array of values of type `N | null | undefined`.
* @param {(BinaryTreeNodeId|N)[]} idsOrNodes - An array of BinaryTreeNodeId or N objects. These can be either the ID
* of a binary tree node or the actual node object itself.
* @param {N['val'][]} [data] - Optional array of values to be added to the nodes. If provided, the length of this
* array should be the same as the length of the `idsOrNodes` array.
* @returns The function `addMany` returns an array of values `(N | null | undefined)[]`.
*/
addMany(data: N[] | Array<N['val']>): (N | null | undefined)[] {
addMany(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N['val'][]): (N | null | undefined)[] {
// TODO not sure addMany not be run multi times
const inserted: (N | null | undefined)[] = [];
const map: Map<N | N['val'], number> = new Map();
const map: Map<N | BinaryTreeNodeId | null, number> = new Map();
if (this.isMergeDuplicatedVal) {
for (const nodeOrId of data) map.set(nodeOrId, (map.get(nodeOrId) ?? 0) + 1);
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
}
for (const nodeOrId of data) {
if (nodeOrId instanceof AbstractBinaryTreeNode) {
inserted.push(this.add(nodeOrId.id, nodeOrId.val));
for (let i = 0; i < idsOrNodes.length; i++) {
const idOrNode = idsOrNodes[i];
if (idOrNode instanceof AbstractBinaryTreeNode) {
inserted.push(this.add(idOrNode.id, idOrNode.val));
continue;
}
if (nodeOrId === null) {
inserted.push(this.add(NaN, null, 0));
continue;
}
// TODO will this cause an issue?
const count = this.isMergeDuplicatedVal ? map.get(nodeOrId) : 1;
let newId: BinaryTreeNodeId;
if (typeof nodeOrId === 'number') {
newId = this.autoIncrementId ? this.maxId + 1 : nodeOrId;
} else if (nodeOrId instanceof Object) {
if (this.autoIncrementId) {
newId = this.maxId + 1;
} else {
if (Object.keys(nodeOrId).includes('id')) {
newId = (nodeOrId as ObjectWithNumberId).id;
} else {
console.warn(nodeOrId, 'Object value must has an id property when the autoIncrementId is false');
continue;
}
}
} else {
console.warn(nodeOrId, ` is not added`);
if (idOrNode === null) {
inserted.push(this.add(null));
continue;
}
const val = data?.[i];
if (this.isMergeDuplicatedVal) {
if (map.has(nodeOrId)) {
inserted.push(this.add(newId, nodeOrId, count));
map.delete(nodeOrId);
if (map.has(idOrNode)) {
inserted.push(this.add(idOrNode, val));
map.delete(idOrNode);
}
} else {
inserted.push(this.add(newId, nodeOrId, 1));
inserted.push(this.add(idOrNode, val));
}
this._setMaxId(newId);
}
return inserted;
}
/**
* The `fill` function clears the current data and adds new data, returning a boolean indicating if the operation was
* successful.
* @param {N[] | Array<N['val']>} data - The `data` parameter can be either an array of objects or an array of arrays.
* Each object or array should have a property called `val`.
* @returns a boolean value.
* The `fill` function clears the binary tree and adds multiple nodes with the given IDs or nodes and optional data.
* @param {(BinaryTreeNodeId | N)[]} idsOrNodes - The `idsOrNodes` parameter is an array that can contain either
* `BinaryTreeNodeId` or `N` values.
* @param {N[] | Array<N['val']>} [data] - The `data` parameter is an optional array of values that will be assigned to
* the nodes being added. If provided, the length of the `data` array should be equal to the length of the `idsOrNodes`
* array. Each value in the `data` array will be assigned to the
* @returns The method is returning a boolean value.
*/
fill(data: N[] | Array<N['val']>): boolean {
fill(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N[] | Array<N['val']>): boolean {
this.clear();
return data.length === this.addMany(data).length;
return idsOrNodes.length === this.addMany(idsOrNodes, data).length;
}
/**
@ -1375,15 +1354,6 @@ export abstract class AbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val
this._visitedLeftSum = value;
}
/**
* The function sets the value of the _autoIncrementId property.
* @param {boolean} value - The value parameter is a boolean that determines whether the id should be automatically
* incremented or not. If value is true, the id will be automatically incremented. If value is false, the id will not
* be automatically incremented.
*/
protected _setAutoIncrementId(value: boolean) {
this._autoIncrementId = value;
}
/**
* The function sets the maximum ID value.

View file

@ -10,6 +10,9 @@ import type {AVLTreeNodeNested, AVLTreeOptions, BinaryTreeDeletedResult, BinaryT
import {IAVLTree, IAVLTreeNode} from '../interfaces';
export class AVLTreeNode<T = any, NEIGHBOR extends AVLTreeNode<T, NEIGHBOR> = AVLTreeNodeNested<T>> extends BSTNode<T, NEIGHBOR> implements IAVLTreeNode<T, NEIGHBOR> {
constructor(id: BinaryTreeNodeId, val?: T) {
super(id, val);
}
}
export class AVLTree<N extends AVLTreeNode<N['val'], N> = AVLTreeNode> extends BST<N> implements IAVLTree<N> {

View file

@ -8,10 +8,12 @@
import type {BinaryTreeNodeId, BinaryTreeNodeNested, BinaryTreeOptions} from '../types';
import {AbstractBinaryTree, AbstractBinaryTreeNode} from './abstract-binary-tree';
import {IBinaryTree, IBinaryTreeNode} from '../interfaces/binary-tree';
import {IBinaryTree, IBinaryTreeNode} from '../interfaces';
export class BinaryTreeNode<T = any, NEIGHBOR extends BinaryTreeNode<T, NEIGHBOR> = BinaryTreeNodeNested<T>> extends AbstractBinaryTreeNode<T, NEIGHBOR> implements IBinaryTreeNode<T, NEIGHBOR> {
constructor(id: BinaryTreeNodeId, val?: T) {
super(id, val);
}
}
export class BinaryTree<N extends BinaryTreeNode<N['val'], N> = BinaryTreeNode> extends AbstractBinaryTree<N> implements IBinaryTree<N> {

View file

@ -11,7 +11,9 @@ import {BinaryTree, BinaryTreeNode} from './binary-tree';
import {IBST, IBSTNode} from '../interfaces';
export class BSTNode<T = any, NEIGHBOR extends BSTNode<T, NEIGHBOR> = BSTNodeNested<T>> extends BinaryTreeNode<T, NEIGHBOR> implements IBSTNode<T, NEIGHBOR> {
constructor(id: BinaryTreeNodeId, val?: T) {
super(id, val);
}
}
export class BST<N extends BSTNode<N['val'], N> = BSTNode> extends BinaryTree<N> implements IBST<N> {

View file

@ -4,12 +4,12 @@ import {BST, BSTNode} from './bst';
export class RBTreeNode<T = any, NEIGHBOR extends RBTreeNode<T, NEIGHBOR> = RBTreeNodeNested<T>> extends BSTNode<T, NEIGHBOR> implements IRBTreeNode<T, NEIGHBOR> {
constructor(id: BinaryTreeNodeId, color: RBColor, val?: T) {
constructor(id: BinaryTreeNodeId, val?: T, color: RBColor = RBColor.RED) {
super(id, val);
this._color = color;
}
private _color: RBColor = RBColor.RED;
private _color: RBColor;
get color(): RBColor {
return this._color;
@ -60,7 +60,7 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
}
override createNode(id: BinaryTreeNodeId, val?: N['val']): N {
return new RBTreeNode(id, RBColor.RED, val) as N;
return new RBTreeNode(id, val, RBColor.RED) as N;
}
// private override _root: BinaryTreeNode<N> | null = null;

View file

@ -9,7 +9,6 @@ import type {BinaryTreeNodeId, TreeMultisetNodeNested, TreeMultisetOptions} from
import {BinaryTreeDeletedResult, CP, DFSOrderPattern, FamilyPosition, LoopType, NodeOrPropertyName} from '../types';
import {ITreeMultiset, ITreeMultisetNode} from '../interfaces';
import {AVLTree, AVLTreeNode} from './avl-tree';
import {ObjectWithNumberId} from '../../utils';
export class TreeMultisetNode<T = any, NEIGHBOR extends TreeMultisetNode<T, NEIGHBOR> = TreeMultisetNodeNested<T>> extends AVLTreeNode<T, NEIGHBOR> implements ITreeMultisetNode<T, NEIGHBOR> {
@ -28,7 +27,7 @@ export class TreeMultisetNode<T = any, NEIGHBOR extends TreeMultisetNode<T, NEIG
this._count = count;
}
private _count = 1;
private _count: number;
get count(): number {
return this._count;
@ -102,74 +101,77 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
return destNode;
}
/**
* The `add` function adds a new node to a binary tree, updating the size and count properties accordingly, and
* balancing the tree if necessary.
* @param {BinaryTreeNodeId} id - The id parameter represents the identifier of the binary tree node that we want to
* add. It is of type BinaryTreeNodeId.
* @param [val] - The `val` parameter is an optional value that can be assigned to the node being added. If no value is
* provided, it will default to `undefined`.
* @param {number} [count] - The `count` parameter is an optional parameter that specifies the number of times the node
* with the given `id` should be added to the binary tree. If the `count` parameter is not provided, it defaults to 1.
* @returns The `add` method returns the inserted node (`N`), `null`, or `undefined`.
* The `add` function adds a new node to a binary search tree, maintaining the tree's properties and balancing if
* necessary.
* @param {BinaryTreeNodeId | N} idOrNode - The `idOrNode` parameter can be either a `BinaryTreeNodeId` or a `N` (which
* represents a `BinaryTreeNode`).
* @param [val] - The `val` parameter represents the value to be added to the binary tree node.
* @param {number} [count] - The `count` parameter is an optional parameter that specifies the number of times the
* value should be added to the binary tree. If the `count` parameter is not provided, it defaults to 1.
* @returns The method `add` returns either the inserted node (`N`), `null`, or `undefined`.
*/
override add(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null | undefined {
override add(idOrNode: BinaryTreeNodeId | N | null, val?: N['val'], count?: number): N | null | undefined {
count = count ?? 1;
let inserted: N | null = null;
const newNode = this.createNode(id, val, count);
if (this.root === null) {
let inserted: N | null | undefined = undefined;
let newNode;
let id;
if (idOrNode instanceof TreeMultisetNode) {
newNode = this.createNode(idOrNode.id, idOrNode.val, idOrNode.count);
} else if (idOrNode === null) {
newNode = null;
} else {
newNode = this.createNode(idOrNode, val, count);
}
if (!this.root) {
this._setRoot(newNode);
this._setSize(this.size + 1);
this._setCount(this.count + count);
inserted = (this.root);
newNode && this._setCount(this.count + newNode.count);
inserted = this.root;
} else {
let cur = this.root;
let traversing = true;
while (traversing) {
if (cur !== null && newNode !== null) {
if (this._compare(cur.id, id) === CP.eq) {
if (newNode) {
if (cur) {
if (newNode) {
if (this._compare(cur.id, newNode.id) === CP.eq) {
cur.val = newNode.val;
cur.count += count;
cur.count += newNode.count;
this._setCount(this.count + newNode.count);
}
//Duplicates are not accepted.
traversing = false;
inserted = cur;
} else if (this._compare(cur.id, id) === CP.gt) {
// Traverse left of the node
if (cur.left === undefined) {
if (newNode) {
newNode.parent = cur;
}
//Add to the left of the current node
cur.left = newNode;
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count);
traversing = false;
inserted = cur.left;
} else {
//Traverse the left of the current node
if (cur.left) cur = cur.left;
}
} else if (this._compare(cur.id, id) === CP.lt) {
// Traverse right of the node
if (cur.right === undefined) {
if (newNode) {
newNode.parent = cur;
}
//Add to the right of the current node
cur.right = newNode;
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count);
inserted = cur;
} else if (this._compare(cur.id, newNode.id) === CP.gt) {
// Traverse left of the node
if (cur.left === undefined) {
//Add to the left of the current node
cur.left = newNode;
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count);
traversing = false;
inserted = (cur.right);
} else {
//Traverse the left of the current node
if (cur.right) cur = cur.right;
traversing = false;
inserted = cur.left;
} else {
//Traverse the left of the current node
if (cur.left) cur = cur.left;
}
} else if (this._compare(cur.id, newNode.id) === CP.lt) {
// Traverse right of the node
if (cur.right === undefined) {
//Add to the right of the current node
cur.right = newNode;
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count);
traversing = false;
inserted = (cur.right);
} else {
//Traverse the left of the current node
if (cur.right) cur = cur.right;
}
}
} else {
// TODO may need to support null inserted
}
} else {
traversing = false;
@ -192,24 +194,20 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
override addTo(newNode: N | null, parent: N): N | null | undefined {
if (parent) {
if (parent.left === undefined) {
if (newNode) {
newNode.parent = parent;
}
parent.left = newNode;
if (newNode !== null) {
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count ?? 0)
this._setCount(this.count + newNode.count)
}
return parent.left;
} else if (parent.right === undefined) {
if (newNode) {
newNode.parent = parent;
}
parent.right = newNode;
if (newNode !== null) {
this._setSize(this.size + 1);
this._setCount(this.count + newNode.count ?? 0);
this._setCount(this.count + newNode.count);
}
return parent.right;
} else {
@ -221,68 +219,89 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
}
/**
* The `addMany` function inserts multiple items into a binary tree and returns an array of the inserted nodes or
* null/undefined values.
* @param {N[] | N[]} data - The `data` parameter can be either an array of elements of type `N` or an
* array of `N` objects.
* The `addMany` function adds multiple nodes to a binary tree and returns an array of the inserted nodes.
* @param {BinaryTreeNodeId[] | N[]} idsOrNodes - An array of BinaryTreeNodeId objects or N objects. These objects
* represent the IDs or nodes of the binary tree where the values will be added.
* @param {N['val'][]} [data] - Optional array of values to be associated with each node being added. If provided, the
* length of the `data` array should be equal to the length of the `idsOrNodes` array.
* @returns The function `addMany` returns an array of `N`, `null`, or `undefined` values.
*/
override addMany(data: N[] | Array<N['val']>): (N | null | undefined)[] {
override addMany(idsOrNodes: (BinaryTreeNodeId | N)[], data?: N['val'][]): (N | null | undefined)[] {
// TODO not sure addMany not be run multi times
const inserted: (N | null | undefined)[] = [];
const map: Map<N | N['val'], number> = new Map();
const map: Map<N | BinaryTreeNodeId, number> = new Map();
if (this.isMergeDuplicatedVal) {
for (const nodeOrId of data) map.set(nodeOrId, (map.get(nodeOrId) ?? 0) + 1);
for (const idOrNode of idsOrNodes) map.set(idOrNode, (map.get(idOrNode) ?? 0) + 1);
}
for (const nodeOrId of data) {
if (nodeOrId instanceof TreeMultisetNode) {
inserted.push(this.add(nodeOrId.id, nodeOrId.val, nodeOrId.count));
for (let i = 0; i < idsOrNodes.length; i++) {
const idOrNode = idsOrNodes[i];
if (idOrNode instanceof TreeMultisetNode) {
inserted.push(this.add(idOrNode.id, idOrNode.val, idOrNode.count));
continue;
}
if (nodeOrId === null) {
if (idOrNode === null) {
inserted.push(this.add(NaN, null, 0));
continue;
}
// TODO will this cause an issue?
const count = this.isMergeDuplicatedVal ? map.get(nodeOrId) : 1;
let newId: BinaryTreeNodeId;
if (typeof nodeOrId === 'number') {
newId = this.autoIncrementId ? this.maxId + 1 : nodeOrId;
} else if (nodeOrId instanceof Object) {
if (this.autoIncrementId) {
newId = this.maxId + 1;
} else {
if (Object.keys(nodeOrId).includes('id')) {
newId = (nodeOrId as ObjectWithNumberId).id;
} else {
console.warn(nodeOrId, 'Object value must has an id property when the autoIncrementId is false');
continue;
}
}
} else {
console.warn(nodeOrId, ` is not added`);
continue;
}
const count = this.isMergeDuplicatedVal ? map.get(idOrNode) : 1;
const val = data?.[i];
if (this.isMergeDuplicatedVal) {
if (map.has(nodeOrId)) {
inserted.push(this.add(newId, nodeOrId, count));
map.delete(nodeOrId);
if (map.has(idOrNode)) {
inserted.push(this.add(idOrNode, val, count));
map.delete(idOrNode);
}
} else {
inserted.push(this.add(newId, nodeOrId, 1));
inserted.push(this.add(idOrNode, val, 1));
}
this._setMaxId(newId);
}
return inserted;
}
/**
* The `perfectlyBalance` function takes a binary tree, performs a depth-first search to sort the nodes, and then
* constructs a balanced binary search tree using either a recursive or iterative approach.
* @returns The function `perfectlyBalance()` returns a boolean value.
*/
override perfectlyBalance(): boolean {
const sorted = this.DFS('in', 'node'), n = sorted.length;
this.clear();
if (sorted.length < 1) return false;
if (this.loopType === LoopType.RECURSIVE) {
const buildBalanceBST = (l: number, r: number) => {
if (l > r) return;
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
this.add(midNode.id, midNode.val, midNode.count);
buildBalanceBST(l, m - 1);
buildBalanceBST(m + 1, r);
};
buildBalanceBST(0, n - 1);
return true;
} else {
const stack: [[number, number]] = [[0, n - 1]];
while (stack.length > 0) {
const popped = stack.pop();
if (popped) {
const [l, r] = popped;
if (l <= r) {
const m = l + Math.floor((r - l) / 2);
const midNode = sorted[m];
this.add(midNode.id, midNode.val, midNode.count);
stack.push([m + 1, r]);
stack.push([l, m - 1]);
}
}
}
return true;
}
}
/**
* The `remove` function removes a node from a binary search tree and returns the deleted node along with the parent
* node that needs to be balanced.
@ -296,7 +315,7 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
const bstDeletedResult: BinaryTreeDeletedResult<N>[] = [];
if (!this.root) return bstDeletedResult;
const curr: N | null = (typeof nodeOrId === 'number') ? this.get(nodeOrId) : nodeOrId;
const curr: N | null = this.get(nodeOrId);
if (!curr) return bstDeletedResult;
const parent: N | null = curr?.parent ? curr.parent : null;
@ -324,13 +343,17 @@ export class TreeMultiset<N extends TreeMultisetNode<N['val'], N> = TreeMultiset
const parentOfLeftSubTreeMax = leftSubTreeRightMost.parent;
orgCurrent = this.swapLocation(curr, leftSubTreeRightMost);
if (parentOfLeftSubTreeMax) {
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
else parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
if (parentOfLeftSubTreeMax.right === leftSubTreeRightMost) {
parentOfLeftSubTreeMax.right = leftSubTreeRightMost.left;
} else {
parentOfLeftSubTreeMax.left = leftSubTreeRightMost.left;
}
needBalanced = parentOfLeftSubTreeMax;
}
}
}
this._setSize(this.size - 1);
// TODO How to handle when the count of target node is lesser than current node's count
this._setCount(this.count - orgCurrent.count);
}

View file

@ -170,6 +170,7 @@ export abstract class AbstractGraph<V extends AbstractVertex<any>, E extends Abs
addVertex(idOrVertex: VertexId | V, val?: V['val']): boolean {
if (idOrVertex instanceof AbstractVertex) {
return this._addVertexOnly(idOrVertex);
} else {
const newVertex = this.createVertex(idOrVertex, val);
return this._addVertexOnly(newVertex);

View file

@ -44,9 +44,9 @@ export class HeapItem<T = number> {
}
export abstract class Heap<T = number> {
/**
* The constructor function initializes a priority queue with an optional priority extractor function.
* The function is a constructor for a class that initializes a priority callback function based on the
* options provided.
* @param [options] - An optional object that contains configuration options for the Heap.
*/
protected constructor(options?: HeapOptions<T>) {
@ -91,16 +91,9 @@ export abstract class Heap<T = number> {
peek(isItem?: undefined): T | undefined;
peek(isItem: false): T | undefined;
peek(isItem: true): HeapItem<T> | null;
/**
* The `peek` function returns the top item or value in a priority queue, depending on the value of the `isItem`
* parameter.
* @param {boolean} [isItem] - The `isItem` parameter is an optional boolean parameter that determines whether the
* method should return the entire `HeapItem` object or just the value of the item. If `isItem` is set to `true`, the
* method will return the `HeapItem` object. If `isItem`
* @returns The `peek` method returns either a `HeapItem<T>` object, `null`, `T`, or `undefined`. The specific return
* type depends on the value of the `isItem` parameter. If `isItem` is `true`, then the method returns a `HeapItem<T>`
* object or `null` if the heap is empty. If `isItem` is `false`
* The `peek` function returns the top item in the priority queue without removing it.
* @returns The `peek()` method is returning either a `HeapItem<T>` object or `null`.Returns an val with the highest priority in the queue
*/
peek(isItem?: boolean): HeapItem<T> | null | T | undefined {
isItem = isItem ?? false;
@ -111,16 +104,9 @@ export abstract class Heap<T = number> {
peekLast(isItem?: undefined): T | undefined;
peekLast(isItem: false): T | undefined;
peekLast(isItem: true): HeapItem<T> | null;
/**
* The `peekLast` function returns the last item in the heap, either as a `HeapItem` object or just the value depending
* on the `isItem` parameter.
* @param {boolean} [isItem] - A boolean parameter that indicates whether the method should return the HeapItem object
* or just the value of the last item in the heap. If isItem is true, the method will return the HeapItem object. If
* isItem is false or not provided, the method will return the value of the last item
* @returns The method `peekLast` returns either a `HeapItem<T>` object, `null`, `T`, or `undefined`. The specific
* return type depends on the value of the `isItem` parameter. If `isItem` is `true`, then the method returns a
* `HeapItem<T>` object or `null` if there are no items in the heap. If `isItem`
* The `peekLast` function returns the last item in the heap.
* @returns The method `peekLast()` returns either a `HeapItem<T>` object or `null`.Returns an val with the lowest priority in the queue
*/
peekLast(isItem?: boolean): HeapItem<T> | null | T | undefined {
isItem = isItem ?? false;
@ -147,15 +133,9 @@ export abstract class Heap<T = number> {
poll(isItem?: undefined): T | undefined;
poll(isItem: false): T | undefined;
poll(isItem: true): HeapItem<T> | null;
/**
* The `poll` function returns the top item from a priority queue, either as a HeapItem object or its value, depending
* on the value of the `isItem` parameter.
* @param {boolean} [isItem] - The `isItem` parameter is a boolean flag that indicates whether the returned value
* should be a `HeapItem<T>` object or just the value `T` itself. If `isItem` is `true`, the method will return the
* `HeapItem<T>` object, otherwise it will return just
* @returns The function `poll` returns either a `HeapItem<T>` object, `null`, or `T` (the value of the `val` property
* of the `HeapItem<T>` object).
* The `poll` function returns the top item from a priority queue or null if the queue is empty.Removes and returns an val with the highest priority in the queue
* @returns either a HeapItem<T> object or null.
*/
poll(isItem?: boolean): HeapItem<T> | null | T | undefined {
isItem = isItem ?? false;
@ -167,8 +147,8 @@ export abstract class Heap<T = number> {
}
/**
* The `has` function checks if a given node or value exists in the priority queue.
* @param {T | HeapItem<T>} node - The `node` parameter can be of type `T` or `HeapItem<T>`.
* The function checks if a given node or value exists in the priority queue.
* @param {T | HeapItem<T>} node - The parameter `node` can be of type `T` or `HeapItem<T>`.
* @returns a boolean value.
*/
has(node: T | HeapItem<T>): boolean {
@ -184,15 +164,9 @@ export abstract class Heap<T = number> {
toArray(isItem?: undefined): (T | undefined)[];
toArray(isItem: false): (T | undefined)[];
toArray(isItem: true): (HeapItem<T> | null)[];
/**
* The `toArray` function returns an array of either HeapItem objects or their values, depending on the value of the
* `isItem` parameter.
* @param {boolean} [isItem] - isItem is an optional boolean parameter that determines whether the returned array
* should contain the HeapItem objects or just the values of the HeapItem objects. If isItem is true, the array will
* contain the HeapItem objects. If isItem is false or not provided, the array will contain only the values
* @returns The method `toArray` returns an array of `HeapItem<T>` objects, or an array of `T` values if the `isItem`
* parameter is set to `false`.
* The `toArray` function returns an array of `HeapItem<T>` objects.
* @returns An array of HeapItem<T> objects.Returns a sorted list of vals
*/
toArray(isItem?: boolean): (HeapItem<T> | null | T | undefined)[] {
isItem = isItem ?? false;

View file

@ -55,8 +55,6 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
get visitedLeftSum(): number[]
get autoIncrementId(): boolean
get maxId(): number
get isMergeDuplicatedVal(): boolean
@ -71,13 +69,13 @@ export interface IAbstractBinaryTree<N extends AbstractBinaryTreeNode<N['val'],
isEmpty(): boolean
add(id: BinaryTreeNodeId, val?: N['val'], count?: number): N | null | undefined
add(id: BinaryTreeNodeId | N, val?: N['val']): N | null | undefined
addTo(newNode: N | null, parent: N): N | null | undefined
addMany(data: N[] | Array<N['val']>): (N | null | undefined)[]
addMany(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N['val'][]): (N | null | undefined)[]
fill(data: N[] | Array<N['val']>): boolean
fill(idsOrNodes: (BinaryTreeNodeId | N | null)[], data?: N[] | Array<N['val']>): boolean
remove(id: BinaryTreeNodeId, ignoreCount?: boolean): BinaryTreeDeletedResult<N>[]

View file

@ -37,6 +37,5 @@ export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, Abstract
export type AbstractBinaryTreeOptions = {
loopType?: LoopType,
autoIncrementId?: boolean,
isMergeDuplicatedVal?: boolean
}

View file

@ -3,15 +3,15 @@ const {MaxHeap, MinHeap} = require('heap-typed');
describe('JS Heap Operation Test', () => {
it('should numeric heap work well', function () {
const minNumHeap = new MinHeap();
// minNumHeap.add(1).add(6).add(2).add(0).add(5).add(9);
// expect(minNumHeap.poll()).toBe(0);
// expect(minNumHeap.poll()).toBe(1);
// expect(minNumHeap.peek()).toBe(2);
// expect(minNumHeap.toArray().length).toBe(4);
// expect(minNumHeap.toArray()[0]).toBe(2);
// expect(minNumHeap.toArray()[1]).toBe(5);
// expect(minNumHeap.toArray()[2]).toBe(9);
// expect(minNumHeap.toArray()[3]).toBe(6);
minNumHeap.add(1).add(6).add(2).add(0).add(5).add(9);
expect(minNumHeap.poll()).toBe(0);
expect(minNumHeap.poll()).toBe(1);
expect(minNumHeap.peek()).toBe(2);
expect(minNumHeap.toArray().length).toBe(4);
expect(minNumHeap.toArray()[0]).toBe(2);
expect(minNumHeap.toArray()[1]).toBe(5);
expect(minNumHeap.toArray()[2]).toBe(9);
expect(minNumHeap.toArray()[3]).toBe(6);
});

View file

@ -4,9 +4,10 @@ describe('BST operations test', () => {
it('should perform various operations on a Binary Search Tree with numeric values', () => {
const bst = new BST();
expect(bst).toBeInstanceOf(BST);
bst.add(11);
bst.add(3);
bst.addMany([15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
bst.add(11, 11);
bst.add(3, 3);
const idsAndValues = [15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
bst.addMany(idsAndValues, idsAndValues);
expect(bst.root).toBeInstanceOf(BSTNode);
if (bst.root) expect(bst.root.id).toBe(11);
@ -193,7 +194,7 @@ describe('BST operations test', () => {
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}];
objBST.addMany(values);
objBST.addMany(values.map(item => item.id), values);
expect(objBST.root).toBeInstanceOf(BSTNode);

View file

@ -5,9 +5,10 @@ describe('TreeMultiset operations test', () => {
const treeMultiset = new TreeMultiset();
expect(treeMultiset instanceof TreeMultiset);
treeMultiset.add(11);
treeMultiset.add(3);
treeMultiset.addMany([11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5]);
treeMultiset.add(11, 11);
treeMultiset.add(3, 3);
const idAndValues = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
treeMultiset.addMany(idAndValues, idAndValues);
expect(treeMultiset.root instanceof TreeMultisetNode);
if (treeMultiset.root) expect(treeMultiset.root.id == 11);
@ -199,7 +200,7 @@ describe('TreeMultiset operations test', () => {
expect(bfsNodes[1].id).toBe(2);
expect(bfsNodes[2].id).toBe(16);
expect(treeMultiset.count).toBe(3);
expect(treeMultiset.count).toBe(9);
});
it('should perform various operations on a Binary Search Tree with object values', () => {
@ -213,7 +214,7 @@ describe('TreeMultiset operations test', () => {
{id: 14, keyA: 14}, {id: 4, keyA: 4}, {id: 7, keyA: 7},
{id: 10, keyA: 10}, {id: 5, keyA: 5}];
objTreeMultiset.addMany(values);
objTreeMultiset.addMany(values.map(item => item.id), values);
expect(objTreeMultiset.root).toBeInstanceOf(TreeMultisetNode);