mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
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:
parent
bd71edc536
commit
2d1010b352
228
package-lock.json
generated
228
package-lock.json
generated
|
@ -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",
|
||||
|
|
25
package.json
25
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>[]
|
||||
|
||||
|
|
|
@ -37,6 +37,5 @@ export type AbstractBinaryTreeNodeNested<T> = AbstractBinaryTreeNode<T, Abstract
|
|||
|
||||
export type AbstractBinaryTreeOptions = {
|
||||
loopType?: LoopType,
|
||||
autoIncrementId?: boolean,
|
||||
isMergeDuplicatedVal?: boolean
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue