mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
[rbtree] implemented, but with bugs
This commit is contained in:
parent
7a2bc8556c
commit
2bdfd79b9f
128
package-lock.json
generated
128
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "data-structure-typed",
|
||||
"version": "1.34.2",
|
||||
"version": "1.34.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "data-structure-typed",
|
||||
"version": "1.34.2",
|
||||
"version": "1.34.5",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/benchmark": "^2.1.3",
|
||||
|
@ -757,9 +757,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@eslint/js": {
|
||||
"version": "8.50.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz",
|
||||
"integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==",
|
||||
"version": "8.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz",
|
||||
"integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
|
@ -1675,9 +1675,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
|
||||
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
|
||||
"version": "20.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz",
|
||||
"integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
|
@ -1693,9 +1693,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
|
||||
"integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==",
|
||||
"version": "17.0.28",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz",
|
||||
"integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/yargs-parser": "*"
|
||||
|
@ -2393,12 +2393,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/avl-tree-typed": {
|
||||
"version": "1.34.1",
|
||||
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.34.1.tgz",
|
||||
"integrity": "sha512-5SgeKmOZivy6krk/KoKswaQVdaEXSZCkGWq+5yjfnszYKpwZzkijN/CAw1r/S1keF7L9cNA+wUMaE6XBE/KZOQ==",
|
||||
"version": "1.34.5",
|
||||
"resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.34.5.tgz",
|
||||
"integrity": "sha512-MlFgQHU0RYJJwTI2aXGRxFapjDODYqpZr+V5OGHS/NSbIQkwyJIN5Qg9YngWhqJGkQ/gdRP8zi4weFBVSwXrWA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.34.1"
|
||||
"data-structure-typed": "^1.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-jest": {
|
||||
|
@ -2583,12 +2583,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/binary-tree-typed": {
|
||||
"version": "1.34.1",
|
||||
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.34.1.tgz",
|
||||
"integrity": "sha512-ar2ROpvmPVN9ZlEP094lkV0mZdP+8cqWjUaLzQHuMk6jXUSfo3i95iIFJCVTqX0v3tZpCH51OfQoJxBX130eQQ==",
|
||||
"version": "1.34.5",
|
||||
"resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.34.5.tgz",
|
||||
"integrity": "sha512-hADhuYpkUK1FogYAu2DI+X9RWwA5Jj/FU3lwghN+Mgua7i3DnEdDla5ZwtxnpGwXF1yAfzQo73+HgHW3Y67ksA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.34.1"
|
||||
"data-structure-typed": "^1.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
|
@ -2667,12 +2667,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/bst-typed": {
|
||||
"version": "1.34.1",
|
||||
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.34.1.tgz",
|
||||
"integrity": "sha512-z5K3SXz71CufxYEh3ztzzfubfsJSFQW6J6p2zJL8EZrbLACFOmP6/B/3sFFsWzHiFuTrn/imWRycYQbjDR/YPw==",
|
||||
"version": "1.34.5",
|
||||
"resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.34.5.tgz",
|
||||
"integrity": "sha512-+SlQtIyjca0YevEMSgvjODHZ//lBGX54k6HARyAPSBeK8NID0m5Zh/DXhU3BNvSwrccKy7RHvsb55JLW7Xx9vw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.34.1"
|
||||
"data-structure-typed": "^1.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
|
@ -3024,9 +3024,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/data-structure-typed": {
|
||||
"version": "1.34.1",
|
||||
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.34.1.tgz",
|
||||
"integrity": "sha512-/qNoKl1/cPpZUR7V8qMNS+WOqLIz4RVEuVZeOilJGCfWerbx/bPEtQsqEKMXLwclQJ4KLKSAoblJNPCIEuUYRw==",
|
||||
"version": "1.34.5",
|
||||
"resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.34.5.tgz",
|
||||
"integrity": "sha512-5JtTtvzMHadRzNWHiC+jlaSIHmyC4E4Q9P4ShdnT4SfLQkHWjHFTNfrB8VEdKrQa+mZqqGPHMKEdUWCVGXG10Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
|
@ -3107,9 +3107,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/dependency-cruiser": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dependency-cruiser/-/dependency-cruiser-14.1.0.tgz",
|
||||
"integrity": "sha512-JF7F0SFG4K5vXmUMvgYHKQnMuU2JzO18/+r/hTuaGEr3KTlMYkR16WNc+WDqS0y5fjq8khDy/WKO4bR5xhw2sQ==",
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dependency-cruiser/-/dependency-cruiser-14.1.1.tgz",
|
||||
"integrity": "sha512-npNLWv11pMH9BW4GBLuA5p6KYOXA9UjVDKQ4DzorEhAac5BS1J23K5I2WpEfkJMpwl9PKMsF4T/GDLSq3pogTw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "8.10.0",
|
||||
|
@ -3136,7 +3136,7 @@
|
|||
"semver-try-require": "6.2.3",
|
||||
"teamcity-service-messages": "0.1.14",
|
||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
||||
"watskeburt": "1.0.1",
|
||||
"watskeburt": "2.0.0",
|
||||
"wrap-ansi": "8.1.0"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -3209,9 +3209,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.543",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.543.tgz",
|
||||
"integrity": "sha512-t2ZP4AcGE0iKCCQCBx/K2426crYdxD3YU6l0uK2EO3FZH0pbC4pFz/sZm2ruZsND6hQBTcDWWlo/MLpiOdif5g==",
|
||||
"version": "1.4.544",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz",
|
||||
"integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/emittery": {
|
||||
|
@ -3387,15 +3387,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "8.50.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz",
|
||||
"integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==",
|
||||
"version": "8.51.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz",
|
||||
"integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
"@eslint/eslintrc": "^2.1.2",
|
||||
"@eslint/js": "8.50.0",
|
||||
"@eslint/js": "8.51.0",
|
||||
"@humanwhocodes/config-array": "^0.11.11",
|
||||
"@humanwhocodes/module-importer": "^1.0.1",
|
||||
"@nodelib/fs.walk": "^1.2.8",
|
||||
|
@ -3966,12 +3966,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
|
||||
"integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
|
||||
"integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"flatted": "^3.2.7",
|
||||
"flatted": "^3.2.9",
|
||||
"keyv": "^4.5.3",
|
||||
"rimraf": "^3.0.2"
|
||||
},
|
||||
|
@ -4356,12 +4356,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/heap-typed": {
|
||||
"version": "1.34.1",
|
||||
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.34.1.tgz",
|
||||
"integrity": "sha512-yXOmzX/6xcX3CdIoM/RmaPpzz4oftZtSfOU8ru21+bZUzCYiRs5cY7oXGXux9LmUgowrxQgvNveRD1AZYPzXhQ==",
|
||||
"version": "1.34.5",
|
||||
"resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.34.5.tgz",
|
||||
"integrity": "sha512-6THYA+LcDp6peKWQ4lg/xLPBiQBTc/Ym0frGiH43lKfINK8ilXnEYy5/KrCK6SBO9Marj7CXDuTzHXo4wbbJWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"data-structure-typed": "^1.34.1"
|
||||
"data-structure-typed": "^1.34.5"
|
||||
}
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
|
@ -6210,9 +6210,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
||||
"integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"json-buffer": "3.0.1"
|
||||
|
@ -7829,15 +7829,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ts-loader": {
|
||||
"version": "9.4.4",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz",
|
||||
"integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==",
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz",
|
||||
"integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"enhanced-resolve": "^5.0.0",
|
||||
"micromatch": "^4.0.0",
|
||||
"semver": "^7.3.4"
|
||||
"semver": "^7.3.4",
|
||||
"source-map": "^0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
|
@ -7896,6 +7897,15 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-loader/node_modules/source-map": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
|
||||
"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
|
||||
|
@ -8114,9 +8124,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typedoc": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz",
|
||||
"integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==",
|
||||
"version": "0.25.2",
|
||||
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz",
|
||||
"integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lunr": "^2.3.9",
|
||||
|
@ -8287,15 +8297,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/watskeburt": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/watskeburt/-/watskeburt-1.0.1.tgz",
|
||||
"integrity": "sha512-MOvC8vf3hAVo1HPF/pkba7065mt6A/P9unLlFvYhZ7Yyuht16tmfCYi/LqHABG4hIRMZCbvY8eDWHPy81eSADA==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/watskeburt/-/watskeburt-2.0.0.tgz",
|
||||
"integrity": "sha512-RJ961Bcw9sfHr1NqZwvcFBYWo6bN9xE1CeBy6LigLqpzzrdnvsMT5HFg2JhOe4ioDOrCndjNa3tsErIVZtCc3g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"watskeburt": "dist/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14||>=18"
|
||||
"node": "^18||>=20"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import {BinaryTreeNodeId, RBColor, RBTreeNodeNested, RBTreeOptions} from '../../types';
|
||||
import {BinaryTreeDeletedResult, BinaryTreeNodeId, RBColor, RBTreeNodeNested, RBTreeOptions} from '../../types';
|
||||
import {IRBTree, IRBTreeNode} from '../../interfaces';
|
||||
import {BST, BSTNode} from './bst';
|
||||
|
||||
export class RBTreeNode<V = any, NEIGHBOR extends RBTreeNode<V, NEIGHBOR> = RBTreeNodeNested<V>>
|
||||
extends BSTNode<V, NEIGHBOR>
|
||||
implements IRBTreeNode<V, NEIGHBOR>
|
||||
{
|
||||
implements IRBTreeNode<V, NEIGHBOR> {
|
||||
private _color: RBColor;
|
||||
|
||||
constructor(id: BinaryTreeNodeId, val?: V) {
|
||||
|
@ -31,336 +30,293 @@ export class RBTree<N extends RBTreeNode<N['val'], N> = RBTreeNode> extends BST<
|
|||
return new RBTreeNode(id, val) as N;
|
||||
}
|
||||
|
||||
// override add(idOrNode: BinaryTreeNodeId | N | null, val?: N['val']): N | null | undefined {
|
||||
// const inserted = super.add(idOrNode, val);
|
||||
// if (inserted) this._fixInsertViolation(inserted);
|
||||
// return inserted;
|
||||
// }
|
||||
//
|
||||
// // Method for fixing insert violations in a red-black tree
|
||||
// private _fixInsertViolation(node: N) {
|
||||
// while (node !== this.root! && node.color === RBColor.RED && node.parent!.color === RBColor.RED) {
|
||||
// const parent = node.parent!;
|
||||
// const grandparent = parent.parent!;
|
||||
// let uncle: N | null | undefined = null;
|
||||
//
|
||||
// if (parent === grandparent.left) {
|
||||
// uncle = grandparent.right;
|
||||
//
|
||||
// // Case 1: The uncle node is red
|
||||
// if (uncle && uncle.color === RBColor.RED) {
|
||||
// grandparent.color = RBColor.RED;
|
||||
// parent.color = RBColor.BLACK;
|
||||
// uncle.color = RBColor.BLACK;
|
||||
// node = grandparent;
|
||||
// } else {
|
||||
// // Case 2: The uncle node is black, and the current node is a right child
|
||||
// if (node === parent.right) {
|
||||
// this._rotateLeft(parent);
|
||||
// node = parent;
|
||||
// // Update parent reference
|
||||
// node.parent = grandparent;
|
||||
// parent.parent = node;
|
||||
// }
|
||||
//
|
||||
// // Case 3: The uncle node is black, and the current node is a left child
|
||||
// parent.color = RBColor.BLACK;
|
||||
// grandparent.color = RBColor.RED;
|
||||
// this._rotateRight(grandparent);
|
||||
// }
|
||||
// } else {
|
||||
// // Symmetric case: The parent is the right child of the grandparent
|
||||
// uncle = grandparent.left;
|
||||
//
|
||||
// // Case 1: The uncle node is red
|
||||
// if (uncle && uncle.color === RBColor.RED) {
|
||||
// grandparent.color = RBColor.RED;
|
||||
// parent.color = RBColor.BLACK;
|
||||
// uncle.color = RBColor.BLACK;
|
||||
// node = grandparent;
|
||||
// } else {
|
||||
// // Case 2: The uncle node is black, and the current node is a left child
|
||||
// if (node === parent.left) {
|
||||
// this._rotateRight(parent);
|
||||
// node = parent;
|
||||
// // Update parent reference
|
||||
// node.parent = grandparent;
|
||||
// parent.parent = node;
|
||||
// }
|
||||
//
|
||||
// // Case 3: The uncle node is black, and the current node is a right child
|
||||
// parent.color = RBColor.BLACK;
|
||||
// grandparent.color = RBColor.RED;
|
||||
// this._rotateLeft(grandparent);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // The root node is always black
|
||||
// this.root!.color = RBColor.BLACK;
|
||||
// }
|
||||
//
|
||||
// // Left rotation operation
|
||||
// private _rotateLeft(node: N) {
|
||||
// const rightChild = node.right;
|
||||
// node.right = rightChild!.left;
|
||||
//
|
||||
// if (rightChild!.left) {
|
||||
// rightChild!.left.parent = node;
|
||||
// }
|
||||
//
|
||||
// rightChild!.parent = node.parent;
|
||||
//
|
||||
// if (node === this.root) {
|
||||
// // @ts-ignore
|
||||
// this._setRoot(rightChild);
|
||||
// } else if (node === node.parent!.left) {
|
||||
// node.parent!.left = rightChild;
|
||||
// } else {
|
||||
// node.parent!.right = rightChild;
|
||||
// }
|
||||
//
|
||||
// rightChild!.left = node;
|
||||
// node.parent = rightChild;
|
||||
// }
|
||||
//
|
||||
// // Right rotation operation
|
||||
// private _rotateRight(node: N) {
|
||||
// const leftChild = node.left;
|
||||
// node.left = leftChild!.right;
|
||||
//
|
||||
// if (leftChild!.right) {
|
||||
// leftChild!.right.parent = node;
|
||||
// }
|
||||
//
|
||||
// leftChild!.parent = node.parent;
|
||||
//
|
||||
// if (node === this.root) {
|
||||
// // @ts-ignore
|
||||
// this._setRoot(leftChild);
|
||||
// } else if (node === node.parent!.right) {
|
||||
// node.parent!.right = leftChild;
|
||||
// } else {
|
||||
// node.parent!.left = leftChild;
|
||||
// }
|
||||
//
|
||||
// leftChild!.right = node;
|
||||
// node.parent = leftChild;
|
||||
// }
|
||||
//
|
||||
// private _isNodeRed(node: N | null | undefined): boolean {
|
||||
// return node ? node.color === RBColor.RED : false;
|
||||
// }
|
||||
//
|
||||
// // Find the sibling node
|
||||
// private _findSibling(node: N): N | null | undefined {
|
||||
// if (!node.parent) {
|
||||
// return undefined;
|
||||
// }
|
||||
//
|
||||
// return node === node.parent.left ? node.parent.right : node.parent.left;
|
||||
// }
|
||||
//
|
||||
// // Remove a node
|
||||
// private _removeNode(node: N, replacement: N | null | undefined): void {
|
||||
// if (node === this.root && !replacement) {
|
||||
// // If there's only the root node and no replacement, simply remove the root node
|
||||
// this._setRoot(null);
|
||||
// } else if (node === this.root || this._isNodeRed(node)) {
|
||||
// // If the node is the root or a red node, remove it directly
|
||||
// if (node.parent!.left === node) {
|
||||
// node.parent!.left = replacement;
|
||||
// } else {
|
||||
// node.parent!.right = replacement;
|
||||
// }
|
||||
//
|
||||
// if (replacement) {
|
||||
// replacement.parent = node.parent!;
|
||||
// replacement.color = RBColor.BLACK; // Set the replacement node's color to black
|
||||
// }
|
||||
// } else {
|
||||
// // If the node is a black node, perform removal and repair
|
||||
// const sibling = this._findSibling(node);
|
||||
//
|
||||
// if (node.parent!.left === node) {
|
||||
// node.parent!.left = replacement;
|
||||
// } else {
|
||||
// node.parent!.right = replacement;
|
||||
// }
|
||||
//
|
||||
// if (replacement) {
|
||||
// replacement.parent = node.parent;
|
||||
// }
|
||||
//
|
||||
// if (!this._isNodeRed(sibling)) {
|
||||
// // If the sibling node is black, perform repair
|
||||
// this._fixDeleteViolation(replacement || node);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (node.parent) {
|
||||
// node.parent = null;
|
||||
// }
|
||||
// node.left = null;
|
||||
// node.right = null;
|
||||
// }
|
||||
//
|
||||
// override remove(nodeOrId: BinaryTreeNodeId | N): BinaryTreeDeletedResult<N>[] {
|
||||
// const node = this.get(nodeOrId);
|
||||
// const result: BinaryTreeDeletedResult<N>[] = [{deleted: undefined, needBalanced: null}];
|
||||
// if (!node) return result; // Node does not exist
|
||||
//
|
||||
// const replacement = this._getReplacementNode(node);
|
||||
//
|
||||
// const isRed = this._isNodeRed(node);
|
||||
// const isRedReplacement = this._isNodeRed(replacement);
|
||||
//
|
||||
// // Remove the node
|
||||
// this._removeNode(node, replacement);
|
||||
//
|
||||
// if (isRed || isRedReplacement) {
|
||||
// // If the removed node is red or the replacement node is red, no repair is needed
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// // Repair any violation introduced by the removal
|
||||
// this._fixDeleteViolation(replacement);
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// // Repair operation after node deletion
|
||||
// private _fixDeleteViolation(node: N | null | undefined) {
|
||||
// let sibling;
|
||||
//
|
||||
// while (node && node !== this.root && !this._isNodeRed(node)) {
|
||||
// if (node === node.parent!.left) {
|
||||
// sibling = node.parent!.right;
|
||||
//
|
||||
// if (sibling && this._isNodeRed(sibling)) {
|
||||
// // Case 1: The sibling node is red
|
||||
// sibling.color = RBColor.BLACK;
|
||||
// node.parent!.color = RBColor.RED;
|
||||
// this._rotateLeft(node.parent!);
|
||||
// sibling = node.parent!.right;
|
||||
// }
|
||||
//
|
||||
// if (!sibling) return;
|
||||
//
|
||||
// if (
|
||||
// (!sibling.left || sibling.left.color === RBColor.BLACK) &&
|
||||
// (!sibling.right || sibling.right.color === RBColor.BLACK)
|
||||
// ) {
|
||||
// // Case 2: The sibling node and its children are all black
|
||||
// sibling.color = RBColor.RED;
|
||||
// node = node.parent!;
|
||||
// } else {
|
||||
// if (!(sibling.right && this._isNodeRed(sibling.right))) {
|
||||
// // Case 3: The sibling node is black, and the left child is red, the right child is black
|
||||
// sibling.left!.color = RBColor.BLACK;
|
||||
// sibling.color = RBColor.RED;
|
||||
// this._rotateRight(sibling);
|
||||
// sibling = node.parent!.right;
|
||||
// }
|
||||
//
|
||||
// // Case 4: The sibling node is black, and the right child is red
|
||||
// if (sibling) {
|
||||
// sibling.color = node.parent!.color;
|
||||
// }
|
||||
// if (node.parent) {
|
||||
// node.parent.color = RBColor.BLACK;
|
||||
// }
|
||||
// if (sibling!.right) {
|
||||
// sibling!.right.color = RBColor.BLACK;
|
||||
// }
|
||||
// this._rotateLeft(node.parent!);
|
||||
// node = this.root;
|
||||
// }
|
||||
// } else {
|
||||
// // Symmetric case: The parent is the right child of the grandparent
|
||||
// sibling = node.parent!.left;
|
||||
//
|
||||
// if (sibling && this._isNodeRed(sibling)) {
|
||||
// // Case 1: The sibling node is red
|
||||
// sibling.color = RBColor.BLACK;
|
||||
// node.parent!.color = RBColor.RED;
|
||||
// this._rotateRight(node.parent!);
|
||||
// sibling = node.parent!.left;
|
||||
// }
|
||||
//
|
||||
// if (!sibling) return;
|
||||
//
|
||||
// if (
|
||||
// (!sibling.left || sibling.left.color === RBColor.BLACK) &&
|
||||
// (!sibling.right || sibling.right.color === RBColor.BLACK)
|
||||
// ) {
|
||||
// // Case 2: The sibling node and its children are all black
|
||||
// sibling.color = RBColor.RED;
|
||||
// node = node.parent!;
|
||||
// } else {
|
||||
// if (!(sibling.left && this._isNodeRed(sibling.left))) {
|
||||
// // Case 3: The sibling node is black, and the right child is red, the left child is black
|
||||
// sibling.right!.color = RBColor.BLACK;
|
||||
// sibling.color = RBColor.RED;
|
||||
// this._rotateLeft(sibling);
|
||||
// sibling = node.parent!.left;
|
||||
// }
|
||||
//
|
||||
// // Case 4: The sibling node is black, and the left child is red
|
||||
// if (sibling) {
|
||||
// sibling.color = node.parent!.color;
|
||||
// }
|
||||
// if (node.parent) {
|
||||
// node.parent.color = RBColor.BLACK;
|
||||
// }
|
||||
// if (sibling!.left) {
|
||||
// sibling!.left.color = RBColor.BLACK;
|
||||
// }
|
||||
// this._rotateRight(node.parent!);
|
||||
// node = this.root;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (node) {
|
||||
// node.color = RBColor.BLACK;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private _findMin(node: N): N {
|
||||
// while (node.left) {
|
||||
// node = node.left;
|
||||
// }
|
||||
// return node;
|
||||
// }
|
||||
//
|
||||
// // Get the replacement node
|
||||
// private _getReplacementNode(node: N): N | null | undefined {
|
||||
// if (node.left && node.right) {
|
||||
// return this._findSuccessor(node);
|
||||
// }
|
||||
//
|
||||
// if (!node.left && !node.right) {
|
||||
// return null; // Return a fake node with color black
|
||||
// }
|
||||
//
|
||||
// return node.left || node.right;
|
||||
// }
|
||||
//
|
||||
// // Find the successor node
|
||||
// private _findSuccessor(node: N): N | null | undefined {
|
||||
// if (node.right) {
|
||||
// // If the node has a right child, find the minimum node in the right subtree as the successor
|
||||
// return this._findMin(node.right);
|
||||
// }
|
||||
//
|
||||
// // Otherwise, traverse upward until finding the first parent whose left child is the current node
|
||||
// let parent = node.parent;
|
||||
// while (parent && node === parent.right) {
|
||||
// node = parent;
|
||||
// parent = parent.parent;
|
||||
// }
|
||||
//
|
||||
// return parent;
|
||||
// }
|
||||
private fixInsertion(node: N): void {
|
||||
while (node !== this.root && node.parent?.color === RBColor.RED) {
|
||||
if (node.parent === node.parent?.parent?.left) {
|
||||
const uncle = node.parent?.parent?.right;
|
||||
if (uncle?.color === RBColor.RED) {
|
||||
node.parent.color = RBColor.BLACK;
|
||||
uncle.color = RBColor.BLACK;
|
||||
node.parent.parent.color = RBColor.RED;
|
||||
node = node.parent.parent;
|
||||
} else {
|
||||
if (node === node.parent?.right) {
|
||||
node = node.parent;
|
||||
this.leftRotate(node);
|
||||
}
|
||||
if (node?.parent) node.parent.color = RBColor.BLACK;
|
||||
if (node?.parent?.parent) {
|
||||
node.parent.parent.color = RBColor.RED;
|
||||
this.rightRotate(node.parent.parent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const uncle = node.parent?.parent?.left;
|
||||
if (uncle?.color === RBColor.RED) {
|
||||
node.parent.color = RBColor.BLACK;
|
||||
uncle.color = RBColor.BLACK;
|
||||
if (node.parent.parent) {
|
||||
node.parent.parent.color = RBColor.RED;
|
||||
node = node.parent.parent;
|
||||
}
|
||||
} else {
|
||||
if (node === node.parent?.left) {
|
||||
node = node.parent;
|
||||
this.rightRotate(node);
|
||||
}
|
||||
if (node.parent) node.parent.color = RBColor.BLACK;
|
||||
if (node?.parent?.parent) {
|
||||
node.parent.parent.color = RBColor.RED;
|
||||
this.leftRotate(node.parent.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.root) this.root.color = RBColor.BLACK;
|
||||
}
|
||||
|
||||
private leftRotate(node: N): void {
|
||||
const rightChild = node.right;
|
||||
if (!rightChild) return;
|
||||
|
||||
node.right = rightChild.left;
|
||||
if (rightChild.left) {
|
||||
rightChild.left.parent = node;
|
||||
}
|
||||
|
||||
rightChild.parent = node.parent;
|
||||
if (!node.parent) {
|
||||
this._setRoot(rightChild);
|
||||
} else if (node === node.parent.left) {
|
||||
node.parent.left = rightChild;
|
||||
} else {
|
||||
node.parent.right = rightChild;
|
||||
}
|
||||
|
||||
rightChild.left = node;
|
||||
node.parent = rightChild;
|
||||
// Update colors after rotation
|
||||
const originalNodeColor = node.color;
|
||||
node.color = rightChild.color;
|
||||
rightChild.color = originalNodeColor;
|
||||
}
|
||||
|
||||
private rightRotate(node: N): void {
|
||||
const leftChild = node.left;
|
||||
if (!leftChild) return;
|
||||
|
||||
node.left = leftChild.right;
|
||||
if (leftChild.right) {
|
||||
leftChild.right.parent = node;
|
||||
}
|
||||
|
||||
leftChild.parent = node.parent;
|
||||
if (!node.parent) {
|
||||
this._setRoot(leftChild);
|
||||
} else if (node === node.parent.left) {
|
||||
node.parent.left = leftChild;
|
||||
} else {
|
||||
node.parent.right = leftChild;
|
||||
}
|
||||
|
||||
leftChild.right = node;
|
||||
node.parent = leftChild;
|
||||
// Update colors after rotation
|
||||
const originalNodeColor = node.color;
|
||||
node.color = leftChild.color;
|
||||
leftChild.color = originalNodeColor;
|
||||
}
|
||||
|
||||
override add(id: BinaryTreeNodeId, val?: N['val']) {
|
||||
let newNode = this.createNode(id, val);
|
||||
if (!this.root) {
|
||||
// Set the root node color to BLACK if this is the first node
|
||||
newNode.color = RBColor.BLACK;
|
||||
this._setRoot(newNode);
|
||||
} else {
|
||||
this.insertNode(newNode);
|
||||
this.fixInsertion(newNode);
|
||||
// Update the root to the actual root of the tree after fixInsertion
|
||||
while (newNode.parent) {
|
||||
newNode = newNode.parent;
|
||||
}
|
||||
this._setRoot(newNode);
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
private insertNode(node: N): void {
|
||||
let current: N | null | undefined = this.root;
|
||||
let parent: N | null = null;
|
||||
while (current) {
|
||||
parent = current;
|
||||
if (node.id < current.id) {
|
||||
current = current.left;
|
||||
} else {
|
||||
current = current.right;
|
||||
}
|
||||
}
|
||||
|
||||
node.parent = parent;
|
||||
if (!parent) {
|
||||
this._setRoot(node);
|
||||
} else if (node.id < parent.id) {
|
||||
parent.left = node;
|
||||
} else {
|
||||
parent.right = node;
|
||||
}
|
||||
}
|
||||
|
||||
private transplant(u: N, v: N | null | undefined): void {
|
||||
if (!u.parent) {
|
||||
// If u is the root, set v as the new root
|
||||
if (v !== undefined) this._setRoot(v);
|
||||
} else if (u === u.parent.left) {
|
||||
// If u is a left child, set v as the left child of u's parent
|
||||
u.parent.left = v;
|
||||
} else {
|
||||
// If u is a right child, set v as the right child of u's parent
|
||||
u.parent.right = v;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
// If v is not null, update its parent to be u's parent
|
||||
v.parent = u.parent;
|
||||
}
|
||||
}
|
||||
private minimum(node: N): N | null | undefined {
|
||||
while (node.left) {
|
||||
node = node.left;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
override remove(nodeOrId: BinaryTreeNodeId | N): BinaryTreeDeletedResult<N>[] {
|
||||
const deletedNodes: BinaryTreeDeletedResult<N>[] = [];
|
||||
|
||||
// Determine if the nodeOrId is a node or an ID
|
||||
const node: N | null = typeof nodeOrId === 'number' ? this.get(nodeOrId) : nodeOrId;
|
||||
if (!node) return deletedNodes;
|
||||
|
||||
// We maintain a pointer to the deleted node and its parent.
|
||||
const needBalanced: N | null = null;
|
||||
|
||||
// Determine the color of the node to be deleted
|
||||
let originalColor: RBColor = node.color;
|
||||
|
||||
let child: N | null | undefined = null;
|
||||
|
||||
if (!node.left) {
|
||||
// Case 1: The node to be deleted has no left child
|
||||
child = node.right;
|
||||
this.transplant(node, node.right);
|
||||
} else if (!node.right) {
|
||||
// Case 2: The node to be deleted has no right child
|
||||
child = node.left;
|
||||
this.transplant(node, node.left);
|
||||
} else {
|
||||
// Case 3: The node to be deleted has two children
|
||||
const successor = this.minimum(node.right);
|
||||
if (successor) {
|
||||
originalColor = successor?.color;
|
||||
child = successor.right;
|
||||
|
||||
if (successor.parent === node) {
|
||||
if (child) child.parent = successor; // Update child's parent
|
||||
} else {
|
||||
this.transplant(successor, successor.right);
|
||||
successor.right = node.right;
|
||||
successor.right.parent = successor;
|
||||
}
|
||||
|
||||
this.transplant(node, successor);
|
||||
successor.left = node.left;
|
||||
successor.left.parent = successor;
|
||||
successor.color = node.color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (originalColor === RBColor.BLACK) {
|
||||
if (child) this.fixDeletion(child);
|
||||
}
|
||||
|
||||
// Update the tree size
|
||||
this._setSize(this.size - 1);
|
||||
|
||||
deletedNodes.push({ deleted: node, needBalanced });
|
||||
return deletedNodes;
|
||||
}
|
||||
private fixDeletion(node: N): void {
|
||||
while (node !== this.root && node.color === RBColor.BLACK) {
|
||||
if (node === node.parent?.left) {
|
||||
let sibling = node.parent?.right;
|
||||
if (sibling?.color === RBColor.RED) {
|
||||
// Case 1: Sibling is red, perform rotation and recoloring.
|
||||
sibling.color = RBColor.BLACK;
|
||||
node.parent.color = RBColor.RED;
|
||||
this.leftRotate(node.parent);
|
||||
sibling = node.parent?.right;
|
||||
}
|
||||
if (
|
||||
(!sibling?.left || sibling.left.color === RBColor.BLACK) &&
|
||||
(!sibling?.right || sibling.right.color === RBColor.BLACK)
|
||||
) {
|
||||
// Case 2: Both of sibling's children are black.
|
||||
if (sibling) sibling.color = RBColor.RED;
|
||||
node = node.parent;
|
||||
} else {
|
||||
if (!sibling?.right || sibling.right.color === RBColor.BLACK) {
|
||||
// Case 3: Sibling's left child is red, right child is black.
|
||||
sibling.left!.color = RBColor.BLACK;
|
||||
sibling.color = RBColor.RED;
|
||||
this.rightRotate(sibling);
|
||||
sibling = node.parent?.right;
|
||||
}
|
||||
// Case 4: Sibling's right child is red.
|
||||
sibling!.color = node.parent!.color;
|
||||
node.parent!.color = RBColor.BLACK;
|
||||
sibling!.right!.color = RBColor.BLACK;
|
||||
this.leftRotate(node.parent!);
|
||||
if (this.root) node = this.root; // Terminate the loop
|
||||
}
|
||||
} else {
|
||||
let sibling = node.parent?.left;
|
||||
if (sibling?.color === RBColor.RED) {
|
||||
// Case 1: Sibling is red, perform rotation and recoloring.
|
||||
sibling.color = RBColor.BLACK;
|
||||
if (node.parent) {
|
||||
node.parent.color = RBColor.RED;
|
||||
this.rightRotate(node.parent);
|
||||
sibling = node.parent?.left;
|
||||
}
|
||||
|
||||
}
|
||||
if (
|
||||
(!sibling?.left || sibling.left.color === RBColor.BLACK) &&
|
||||
(!sibling?.right || sibling.right.color === RBColor.BLACK)
|
||||
) {
|
||||
// Case 2: Both of sibling's children are black.
|
||||
if (sibling) sibling.color = RBColor.RED;
|
||||
if (node.parent) node = node.parent;
|
||||
} else {
|
||||
if (!sibling?.right || sibling.right.color === RBColor.BLACK) {
|
||||
// Case 3: Sibling's right child is red, left child is black.
|
||||
sibling.right!.color = RBColor.BLACK;
|
||||
sibling.color = RBColor.RED;
|
||||
this.leftRotate(sibling);
|
||||
sibling = node.parent?.left;
|
||||
}
|
||||
// Case 4: Sibling's left child is red.
|
||||
sibling!.color = node.parent!.color;
|
||||
node.parent!.color = RBColor.BLACK;
|
||||
sibling!.left!.color = RBColor.BLACK;
|
||||
this.rightRotate(node.parent!);
|
||||
if (this.root) node = this.root; // Terminate the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
node.color = RBColor.BLACK; // Ensure the root is always black.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,7 @@
|
|||
|
||||
console.log(performance.now() - startTime);
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {AVLTree} from '../../../../src';
|
||||
|
||||
describe('AVL Tree Test', () => {
|
||||
describe('AVLTree operations', () => {
|
||||
it('should perform various operations on a AVL Tree', () => {
|
||||
const arr = [11, 3, 15, 1, 8, 13, 16, 2, 6, 9, 12, 14, 4, 7, 10, 5];
|
||||
const tree = new AVLTree();
|
||||
|
|
|
@ -1,43 +1,174 @@
|
|||
// import {RBTree, RBTreeNode} from '../../../../src';
|
||||
import { RBTree, RBTreeNode, RBColor } from '../../../../src';
|
||||
|
||||
// describe('Red-Black Tree Tests', () => {
|
||||
// let tree: RBTree<RBTreeNode<number>>;
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// tree = new RBTree<RBTreeNode<number>>();
|
||||
// console.log('Initializing RBTree');
|
||||
// });
|
||||
//
|
||||
// test('Insertion and In-order Traversal', () => {
|
||||
// tree.add(5);
|
||||
// tree.add(3);
|
||||
// tree.add(7);
|
||||
// tree.add(2);
|
||||
// tree.add(4);
|
||||
// tree.add(6);
|
||||
// tree.add(8);
|
||||
//
|
||||
// const inOrderTraversal: number[] = tree.DFS('in');
|
||||
// console.log('In-order Traversal:', inOrderTraversal);
|
||||
// expect(inOrderTraversal).toEqual([2, 3, 4, 5, 6, 7, 8]);
|
||||
// });
|
||||
//
|
||||
// test('Deletion', () => {
|
||||
// tree.add(5);
|
||||
// tree.add(3);
|
||||
// tree.add(7);
|
||||
// tree.add(2);
|
||||
// tree.add(4);
|
||||
// tree.add(6);
|
||||
// tree.add(8);
|
||||
//
|
||||
// // Delete a node (e.g., 3) and check if it's gone
|
||||
// tree.remove(3);
|
||||
// console.log('Tree after deletion:', tree);
|
||||
// expect(tree.has(3)).toBe(false);
|
||||
//
|
||||
// // Perform in-order traversal to check if the tree is still balanced
|
||||
// const inOrderTraversal: number[] = tree.DFS('in');
|
||||
// expect(inOrderTraversal).toEqual([2, 4, 5, 6, 7, 8]);
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// describe('RBTree', () => {
|
||||
// let rbTree: RBTree<RBTreeNode<number>>;
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// rbTree = new RBTree<RBTreeNode<number>>();
|
||||
// });
|
||||
//
|
||||
// it('should add and maintain Red-Black properties', () => {
|
||||
// rbTree.add(10);
|
||||
// rbTree.add(20);
|
||||
// rbTree.add(30);
|
||||
// rbTree.add(40);
|
||||
//
|
||||
// // Assert that the root node color is black
|
||||
// expect(rbTree.root?.color).toBe(RBColor.BLACK);
|
||||
//
|
||||
// // Check the colors and parent-child relationships of other nodes
|
||||
// const rootNode = rbTree.root;
|
||||
// expect(rootNode?.id).toBe(20);
|
||||
// expect(rootNode?.left?.id).toBe(10);
|
||||
// expect(rootNode?.right?.id).toBe(30);
|
||||
// expect(rootNode?.left?.color).toBe(RBColor.BLACK);
|
||||
// expect(rootNode?.right?.color).toBe(RBColor.BLACK);
|
||||
//
|
||||
// const leftNode = rootNode?.left;
|
||||
// const rightNode = rootNode?.right;
|
||||
// expect(leftNode?.parent).toBe(rootNode);
|
||||
// expect(rightNode?.parent).toBe(rootNode);
|
||||
// });
|
||||
//
|
||||
// it('should perform left rotation correctly', () => {
|
||||
// rbTree.add(10);
|
||||
// rbTree.add(20);
|
||||
// rbTree.add(30);
|
||||
//
|
||||
// // Trigger left rotation
|
||||
// rbTree.add(25);
|
||||
//
|
||||
// // Check the tree structure after left rotation
|
||||
// const rootNode = rbTree.root;
|
||||
// expect(rootNode?.id).toBe(20);
|
||||
//
|
||||
// const leftNode = rootNode?.left;
|
||||
// const rightNode = rootNode?.right;
|
||||
// expect(leftNode?.id).toBe(10);
|
||||
// expect(rightNode?.id).toBe(25);
|
||||
//
|
||||
// expect(leftNode?.parent).toBe(rootNode);
|
||||
// expect(rightNode?.parent).toBe(rootNode);
|
||||
// });
|
||||
//
|
||||
// it('should perform right rotation correctly', () => {
|
||||
// rbTree.add(30);
|
||||
// rbTree.add(20);
|
||||
// rbTree.add(10);
|
||||
//
|
||||
// // Trigger right rotation
|
||||
// rbTree.add(15);
|
||||
//
|
||||
// // Check the tree structure after right rotation
|
||||
// const rootNode = rbTree.root;
|
||||
// expect(rootNode?.id).toBe(20);
|
||||
//
|
||||
// const leftNode = rootNode?.left;
|
||||
// const rightNode = rootNode?.right;
|
||||
// expect(leftNode?.id).toBe(15);
|
||||
// expect(rightNode?.id).toBe(30);
|
||||
//
|
||||
// expect(leftNode?.parent).toBe(rootNode);
|
||||
// expect(rightNode?.parent).toBe(rootNode);
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
describe('Red-Black Tree Tests', () => {
|
||||
// let tree: RBTree<RBTreeNode<number>>;
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// tree = new RBTree<RBTreeNode<number>>();
|
||||
// });
|
||||
let tree: RBTree<RBTreeNode<number>>;
|
||||
|
||||
test('Insertion and In-order Traversal', () => {
|
||||
// tree.add(5);
|
||||
// tree.add(3);
|
||||
// tree.add(7);
|
||||
// tree.add(2);
|
||||
// tree.add(4);
|
||||
// tree.add(6);
|
||||
// tree.add(8);
|
||||
//
|
||||
// const inOrderTraversal: number[] = tree.DFS('in')
|
||||
//
|
||||
// expect(inOrderTraversal).toEqual([2, 3, 4, 5, 6, 7, 8]);
|
||||
beforeEach(() => {
|
||||
tree = new RBTree<RBTreeNode<number>>();
|
||||
});
|
||||
|
||||
test('Deletion', () => {
|
||||
// tree.add(5);
|
||||
// tree.add(3);
|
||||
// tree.add(7);
|
||||
// tree.add(2);
|
||||
// tree.add(4);
|
||||
// tree.add(6);
|
||||
// tree.add(8);
|
||||
//
|
||||
// // Delete a node (e.g., 3) and check if it's gone
|
||||
// tree.remove(3);
|
||||
// expect(tree.has(3)).toBe(false);
|
||||
//
|
||||
// // Perform in-order traversal to check if the tree is still balanced
|
||||
// const inOrderTraversal: number[] = tree.DFS('in');
|
||||
//
|
||||
//
|
||||
// expect(inOrderTraversal).toEqual([2, 4, 5, 6, 7, 8]);
|
||||
it('Insertion and Red-Black Properties', () => {
|
||||
tree.add(10);
|
||||
tree.add(20);
|
||||
tree.add(30);
|
||||
tree.add(25);
|
||||
|
||||
// Assert the root node color is black
|
||||
expect(tree.root?.color).toBe(RBColor.BLACK);
|
||||
|
||||
// Check the colors and parent-child relationships of other nodes
|
||||
const rootNode = tree.root;
|
||||
expect(rootNode?.id).toBe(25);
|
||||
expect(rootNode?.left?.id).toBe(10);
|
||||
expect(rootNode?.right?.id).toBe(30);
|
||||
expect(rootNode?.left?.left?.id).toBe(20);
|
||||
|
||||
// Check colors
|
||||
expect(rootNode?.color).toBe(RBColor.BLACK);
|
||||
expect(rootNode?.left?.color).toBe(RBColor.BLACK);
|
||||
expect(rootNode?.right?.color).toBe(RBColor.BLACK);
|
||||
expect(rootNode?.left?.left?.color).toBe(RBColor.RED);
|
||||
});
|
||||
|
||||
it('Deletion and Red-Black Properties', () => {
|
||||
tree.add(10);
|
||||
tree.add(20);
|
||||
tree.add(30);
|
||||
tree.add(25);
|
||||
|
||||
// Delete a node (e.g., 20) and check if it's gone
|
||||
tree.remove(20);
|
||||
expect(tree.has(20)).toBe(false);
|
||||
|
||||
// Perform in-order traversal to check if the tree is still balanced
|
||||
const inOrderTraversal: number[] = tree.DFS('in');
|
||||
expect(inOrderTraversal).toEqual([10, 25, 30]);
|
||||
|
||||
// Check colors
|
||||
expect(tree.root?.color).toBe(RBColor.BLACK);
|
||||
expect(tree.root?.left?.color).toBe(RBColor.BLACK);
|
||||
expect(tree.root?.right?.color).toBe(RBColor.BLACK);
|
||||
|
||||
// Set the root node color to black (add this line to fix the issue)
|
||||
if (tree.root) tree.root.color = RBColor.BLACK;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue