feat: Remove support for the 'variant' option parameter in Red-Black Tree, meaning no support for reverse Red-Black Tree.

fix: Fix bug in the return value of the Red-Black Tree delete method.
test: Test the clone methods of all the binary tree data structures.
This commit is contained in:
Revone 2023-12-25 10:56:04 +08:00
parent 50a5c06798
commit eb590d6c27
7 changed files with 210 additions and 19 deletions

View file

@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file.
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- [`auto-changelog`](https://github.com/CookPete/auto-changelog)
## [v1.49.6](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
## [v1.49.7](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
### Changes

View file

@ -1509,8 +1509,8 @@ export class BinaryTree<
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
} else {
if (current.left) queue.push(current.left);
if (current.right) queue.push(current.right);
if (this.isRealNode(current.left)) queue.push(current.left);
if (this.isRealNode(current.right)) queue.push(current.right);
}
traverse(level + 1);
@ -1530,8 +1530,8 @@ export class BinaryTree<
if (current && this.isNodeOrNull(current.left)) queue.push(current.left);
if (current && this.isNodeOrNull(current.right)) queue.push(current.right);
} else {
if (current.left) queue.push(current.left);
if (current.right) queue.push(current.right);
if (this.isRealNode(current.left)) queue.push(current.left);
if (this.isRealNode(current.right)) queue.push(current.right);
}
}
}

View file

@ -106,7 +106,6 @@ export class RedBlackTree<
override createTree(options?: RBTreeOptions<K>): TREE {
return new RedBlackTree<K, V, N, TREE>([], {
iterationType: this.iterationType,
variant: this.variant,
...options
}) as TREE;
}
@ -316,9 +315,9 @@ export class RedBlackTree<
this._fixDelete(x!);
}
this._size--;
ans.push({ deleted: z, needBalanced: undefined });
};
helper(this.root);
// TODO
return ans;
}

View file

@ -7,4 +7,4 @@ export type RedBlackTreeNodeNested<K, V> = RedBlackTreeNode<K, V, RedBlackTreeNo
export type RedBlackTreeNested<K, V, N extends RedBlackTreeNode<K, V, N>> = RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, RedBlackTree<K, V, N, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
export type RBTreeOptions<K> = BSTOptions<K> & {};
export type RBTreeOptions<K> = Omit<BSTOptions<K>, 'variant'> & {};

View file

@ -4,8 +4,8 @@
<meta charset='UTF-8'>
<title>CDN Test</title>
<!-- <script src="../../dist/umd/data-structure-typed.min.js"></script>-->
<!-- <script src="../../dist/umd/data-structure-typed.js"></script>-->
<script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>
<script src="../../dist/umd/data-structure-typed.js"></script>
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.42.2/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.43.3/dist/umd/data-structure-typed.min.js'></script>-->
<!-- <script src='https://cdn.jsdelivr.net/npm/data-structure-typed@1.44.0/dist/umd/data-structure-typed.min.js'></script>-->
@ -114,7 +114,7 @@
try {
const { PriorityQueue: CPriorityQueue } = sdsl;
const { PriorityQueue } = dataStructureTyped;
const pq = new PriorityQueue({ comparator: (a, b) => b - a });
const pq = new PriorityQueue([], { comparator: (a, b) => b - a });
const tS = performance.now();
const n = 1000000;
@ -123,7 +123,7 @@
}
for (let i = 0; i < n; i++) {
pq.pop();
pq.poll();
}
console.log((performance.now() - tS).toFixed(2), `PriorityQueue ${n.toLocaleString()} add`);
console.log(pq.size, `pq.size`);

View file

@ -1,4 +1,4 @@
import { AVLTree, BST } from '../../../../src';
import { AVLTree, BST, BSTVariant, IterationType, RedBlackTree, TreeMultimap } from '../../../../src';
describe('Overall BinaryTree Test', () => {
it('should perform various operations on BinaryTree', () => {
@ -60,4 +60,183 @@ describe('Overall BinaryTree Test', () => {
avlTree.isAVLBalanced(); // true
expect(avlTree.isAVLBalanced()).toBe(true); // true
});
it('Should clone a BST works fine', () => {
const bst = new BST<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
variant: BSTVariant.INVERSE,
extractor: key => key
});
expect(bst.size).toBe(5);
expect(bst.root?.key).toBe(6);
expect(bst.root?.left?.key).toBe(7);
expect(bst.root?.left?.left?.key).toBe(9);
expect(bst.root?.right?.key).toBe(1);
expect(bst.root?.right?.left?.key).toBe(3);
expect(bst.getNodeByKey(7)?.left?.key).toBe(9);
expect(bst.getHeight()).toBe(2);
expect(bst.has(9)).toBe(true);
expect(bst.has(7)).toBe(true);
expect(bst.delete(7)[0].deleted?.key).toBe(7);
expect(bst.has(7)).toBe(false);
expect(bst.size).toBe(4);
expect(bst.root?.key).toBe(6);
expect(bst.root?.left?.key).toBe(9);
expect(bst.root?.right?.key).toBe(1);
expect(bst.root?.right?.left?.key).toBe(3);
expect(bst.getNodeByKey(6)?.left?.key).toBe(9);
expect(bst.getHeight()).toBe(2);
expect(bst.has(9)).toBe(true);
expect(bst.has(7)).toBe(false);
expect(bst.bfs()).toEqual([6, 9, 1, 3]);
const clonedBST = bst.clone();
expect(clonedBST.size).toBe(4);
expect(clonedBST.root?.key).toBe(6);
expect(clonedBST.root?.left?.key).toBe(9);
expect(clonedBST.root?.right?.key).toBe(1);
expect(clonedBST.root?.right?.left?.key).toBe(3);
expect(clonedBST.getNodeByKey(6)?.left?.key).toBe(9);
expect(clonedBST.getHeight()).toBe(2);
expect(clonedBST.has(9)).toBe(true);
expect(clonedBST.has(7)).toBe(false);
expect(clonedBST.bfs()).toEqual([6, 9, 1, 3]);
});
it('Should clone a AVLTree works fine', () => {
const avl = new AVLTree<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
variant: BSTVariant.INVERSE,
extractor: key => key
});
expect(avl.size).toBe(5);
avl.add(2);
avl.add(5);
avl.add(4);
expect(avl.root?.key).toBe(3);
expect(avl.root?.left?.key).toBe(7);
expect(avl.root?.left?.left?.key).toBe(9);
expect(avl.root?.right?.key).toBe(1);
expect(avl.root?.right?.left?.key).toBe(2);
expect(avl.getNodeByKey(7)?.left?.key).toBe(9);
expect(avl.getHeight()).toBe(3);
expect(avl.has(9)).toBe(true);
expect(avl.has(7)).toBe(true);
expect(avl.delete(7)[0].deleted?.key).toBe(7);
expect(avl.has(7)).toBe(false);
expect(avl.size).toBe(7);
expect(avl.root?.key).toBe(3);
expect(avl.root?.left?.key).toBe(5);
expect(avl.root?.right?.key).toBe(1);
expect(avl.root?.right?.left?.key).toBe(2);
expect(avl.getNodeByKey(6)?.left?.key).toBe(undefined);
expect(avl.getHeight()).toBe(3);
expect(avl.has(9)).toBe(true);
expect(avl.has(7)).toBe(false);
expect(avl.bfs()).toEqual([3, 5, 1, 9, 4, 2, 6]);
const clonedAVL = avl.clone();
expect(clonedAVL.size).toBe(7);
expect(clonedAVL.root?.key).toBe(3);
expect(clonedAVL.root?.left?.key).toBe(5);
expect(clonedAVL.root?.right?.key).toBe(1);
expect(clonedAVL.root?.right?.left?.key).toBe(2);
expect(clonedAVL.getNodeByKey(6)?.left?.key).toBe(undefined);
expect(clonedAVL.getHeight()).toBe(3);
expect(clonedAVL.has(9)).toBe(true);
expect(clonedAVL.has(7)).toBe(false);
expect(clonedAVL.bfs()).toEqual([3, 5, 1, 9, 4, 2, 6]);
});
it('Should clone a TreeMultimap works fine', () => {
const tmm = new TreeMultimap<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
variant: BSTVariant.INVERSE,
extractor: key => key
});
expect(tmm.size).toBe(5);
tmm.add(2);
tmm.add(2);
tmm.add(2);
tmm.add(5);
tmm.add(4);
expect(tmm.count).toBe(10);
expect(tmm.root?.key).toBe(3);
expect(tmm.root?.left?.key).toBe(7);
expect(tmm.root?.left?.left?.key).toBe(9);
expect(tmm.root?.right?.key).toBe(1);
expect(tmm.root?.right?.left?.key).toBe(2);
expect(tmm.getNodeByKey(7)?.left?.key).toBe(9);
expect(tmm.getHeight()).toBe(3);
expect(tmm.has(9)).toBe(true);
expect(tmm.has(7)).toBe(true);
expect(tmm.delete(7)[0].deleted?.key).toBe(7);
expect(tmm.has(7)).toBe(false);
expect(tmm.size).toBe(7);
expect(tmm.count).toBe(9);
expect(tmm.root?.key).toBe(3);
expect(tmm.root?.left?.key).toBe(5);
expect(tmm.root?.right?.key).toBe(1);
expect(tmm.root?.right?.left?.key).toBe(2);
expect(tmm.getNodeByKey(6)?.left?.key).toBe(undefined);
expect(tmm.getHeight()).toBe(3);
expect(tmm.has(9)).toBe(true);
expect(tmm.has(7)).toBe(false);
expect(tmm.bfs()).toEqual([3, 5, 1, 9, 4, 2, 6]);
const clonedTMM = tmm.clone();
expect(clonedTMM.size).toBe(7);
expect(clonedTMM.count).toBe(9);
expect(clonedTMM.root?.key).toBe(3);
expect(clonedTMM.root?.left?.key).toBe(5);
expect(clonedTMM.root?.right?.key).toBe(1);
expect(clonedTMM.root?.right?.left?.key).toBe(2);
expect(clonedTMM.getNodeByKey(6)?.left?.key).toBe(undefined);
expect(clonedTMM.getHeight()).toBe(3);
expect(clonedTMM.has(9)).toBe(true);
expect(clonedTMM.has(7)).toBe(false);
expect(clonedTMM.bfs()).toEqual([3, 5, 1, 9, 4, 2, 6]);
});
it('Should clone a RedBlackTree works fine', () => {
const rbTree = new RedBlackTree<number>([3, 6, 7, 1, 9], {
iterationType: IterationType.RECURSIVE,
extractor: key => key
});
expect(rbTree.size).toBe(5);
rbTree.add(2);
rbTree.add(2);
rbTree.add(2);
rbTree.add(5);
rbTree.add(4);
expect(rbTree.root?.key).toBe(3);
expect(rbTree.root?.left?.key).toBe(1);
expect(rbTree.root?.left?.left?.key).toBe(NaN);
expect(rbTree.root?.right?.key).toBe(7);
expect(rbTree.root?.right?.left?.key).toBe(5);
expect(rbTree.getNodeByKey(7)?.left?.key).toBe(5);
expect(rbTree.getHeight()).toBe(4);
expect(rbTree.has(9)).toBe(true);
expect(rbTree.has(7)).toBe(true);
expect(rbTree.delete(7)?.[0]?.deleted?.key).toBe(7);
expect(rbTree.has(7)).toBe(false);
expect(rbTree.size).toBe(7);
expect(rbTree.root?.key).toBe(3);
expect(rbTree.root?.left?.key).toBe(1);
expect(rbTree.root?.right?.key).toBe(5);
expect(rbTree.root?.right?.left?.key).toBe(4);
expect(rbTree.getNodeByKey(6)?.left?.key).toBe(NaN);
expect(rbTree.getHeight()).toBe(4);
expect(rbTree.has(9)).toBe(true);
expect(rbTree.has(7)).toBe(false);
expect(rbTree.bfs()).toEqual([3, 1, 5, 2, 4, 9, 6]);
const clonedRbTree = rbTree.clone();
expect(clonedRbTree.size).toBe(7);
expect(clonedRbTree.root?.key).toBe(3);
expect(clonedRbTree.root?.left?.key).toBe(1);
expect(clonedRbTree.root?.right?.key).toBe(5);
expect(clonedRbTree.root?.right?.left?.key).toBe(4);
expect(clonedRbTree.getNodeByKey(6)?.left?.key).toBe(NaN);
expect(clonedRbTree.getHeight()).toBe(4);
expect(clonedRbTree.has(9)).toBe(true);
expect(clonedRbTree.has(7)).toBe(false);
expect(clonedRbTree.bfs()).toEqual([3, 1, 5, 2, 4, 9, 6]);
});
});

View file

@ -108,12 +108,25 @@ describe('HashMap Test2', () => {
expect(hashMap.get(keyObj)).toBe('objectValue');
});
// it('should handle number keys correctly', () => {
// hashMap.set(999, { a: '999Value' });
// hashMap.set('999', {a: '999StrValue'})
// expect(hashMap.get(999)).toEqual({ a: '999Value' });
// expect(hashMap.get('999')).toEqual({ a: '999StrValue' });
// });
test('Inheritability test', () => {
class ExtendedHashMap<K, V> extends HashMap<K, V> {
constructor(
elements: Iterable<[K, V]> = [],
options?: {
hashFn?: (key: K) => string;
someOtherParam: string;
}
) {
const { someOtherParam, ...restOptions } = options || {};
// do something with someOtherParam
super(elements, restOptions);
}
}
const eHM = new ExtendedHashMap<string, number>([], { someOtherParam: 'someOtherParam' });
eHM.set('one', 1);
expect(eHM.get('one')).toBe(1);
});
it('should update the value for an existing key', () => {
hashMap.set('key1', 'value1');