diff --git a/src/data-structures/binary-tree/bst.ts b/src/data-structures/binary-tree/bst.ts index 94cd873..e033122 100644 --- a/src/data-structures/binary-tree/bst.ts +++ b/src/data-structures/binary-tree/bst.ts @@ -231,10 +231,6 @@ export class BST = BSTNode> * @returns either the first node that matches the given nodeProperty and callback, or null if no * matching node is found. */ -<<<<<<< HEAD - override get(nodeProperty: BinaryTreeNodeKey | N, propertyName: BinaryTreeNodePropertyName = 'key'): N | null { - return this.getNodes(nodeProperty, propertyName, true)[0] ?? undefined; -======= override get>( identifier: ReturnType | null, callback: C = ((node: N) => node.key) as C, @@ -242,7 +238,6 @@ export class BST = BSTNode> iterationType = this.iterationType ): N | null { return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null; ->>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d } /** diff --git a/src/data-structures/binary-tree/rb-tree.ts b/src/data-structures/binary-tree/rb-tree.ts index 7d4c6c1..3018dc7 100644 --- a/src/data-structures/binary-tree/rb-tree.ts +++ b/src/data-structures/binary-tree/rb-tree.ts @@ -1,8 +1,4 @@ -<<<<<<< HEAD -import {BinaryTreeDeletedResult, BinaryTreeNodeKey, RBColor, RBTreeNodeNested, RBTreeOptions} from '../../types'; -======= import {BTNKey, RBColor, RBTreeNodeNested, RBTreeOptions} from '../../types'; ->>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d import {IBinaryTree} from '../../interfaces'; import {BST, BSTNode} from './bst'; @@ -27,317 +23,6 @@ export class RBTree = RBTreeNode root.key) { - if (!root.right) { - root.right = node; - node.parent = root; - } else { - this.insertNode(root.right as N, node); - } - } - } - - private fixInsertViolations(node: N): void { - let parent: N | undefined = undefined; - let grandparent: N | undefined = undefined; - - while (node !== this.root && node.color === RBColor.RED && node.parent?.color === RBColor.RED) { - parent = node.parent as N; - grandparent = parent.parent as N; - - if (parent === grandparent.left) { - const uncle = grandparent.right; - - if (uncle && uncle.color === RBColor.RED) { - grandparent.color = RBColor.RED; - parent.color = RBColor.BLACK; - uncle.color = RBColor.BLACK; - node = grandparent; - } else { - if (node === parent.right) { - this.rotateLeft(parent); - node = parent; - parent = node.parent as N; - } - - this.rotateRight(grandparent as N); - - const tempColor = parent.color; - parent.color = grandparent.color; - grandparent.color = tempColor; - - node = parent; - } - } else { - const uncle = grandparent.left; - - if (uncle && uncle.color === RBColor.RED) { - grandparent.color = RBColor.RED; - parent.color = RBColor.BLACK; - uncle.color = RBColor.BLACK; - node = grandparent; - } else { - if (node === parent.left) { - this.rotateRight(parent); - node = parent; - parent = node.parent as N; - } - - this.rotateLeft(grandparent as N); - - const tempColor = parent.color; - parent.color = grandparent.color; - grandparent.color = tempColor; - - node = parent; - } - } - } - - if (this.root) this.root.color = RBColor.BLACK; - } - - private rotateLeft(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; - } - - private rotateRight(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.right) { - node.parent.right = leftChild; - } else { - node.parent.left = leftChild; - } - leftChild.right = node; - node.parent = leftChild; - } - - remove(nodeOrKey: BinaryTreeNodeKey | N): BinaryTreeDeletedResult[] { - const result: BinaryTreeDeletedResult[] = []; - if (this.root) { - const nodeToRemove = typeof nodeOrKey === 'number' ? this.get(nodeOrKey) : nodeOrKey; - if (nodeToRemove) { - this.deleteNode(nodeToRemove); - this._setSize(this.size - 1); - result.push({deleted: nodeToRemove, needBalanced: undefined}); - } - } - return result; - } - - private deleteNode(node: N): void { - const parent = node.parent as N; - const isLeftChild = parent && node === parent.left; - - if (!node.left && !node.right) { - if (!parent) { - this._setRoot(null); - } else { - if (!isLeftChild) { - parent.right = undefined; - } else { - parent.left = undefined; - } - } - return; - } - - const child = node.left || node.right; - if (child) child.parent = parent; - - if (!parent) { - if (child) { - this._setRoot(child); - if (node.color === RBColor.BLACK && child.color === RBColor.RED) { - child.color = RBColor.BLACK; - } - } - } else { - if (!isLeftChild) { - parent.right = child; - } else { - parent.left = child; - } - - if (node.color === RBColor.BLACK) { - if (child && child.color === RBColor.RED) { - // 如果删除的节点是黑色,而子节点是红色,直接将子节点染成黑色 - child.color = RBColor.BLACK; - } else { - // 否则,进入修复违反红黑树性质的情况 - this.fixDeleteViolations(child, parent, isLeftChild); - } - } - - } - } - - private fixDeleteViolations(node: N | null | undefined, parent: N | undefined, isLeftChild: boolean): void { - let sibling: N | undefined; - - while (node !== this.root && (!node || node.color === RBColor.BLACK)) { - if (isLeftChild) { - sibling = parent?.right as N; - - if (sibling?.color === RBColor.RED) { - // Case 1: Sibling is red, transform into a case where sibling is black - sibling.color = RBColor.BLACK; - parent!.color = RBColor.RED; - this.rotateLeft(parent!); - sibling = parent!.right as N; - } - - if ( - (!sibling?.left || sibling.left.color === RBColor.BLACK) && - (!sibling?.right || sibling.right.color === RBColor.BLACK) - ) { - // Case 2: Sibling and both of its children are black - sibling.color = RBColor.RED; - node = parent; - parent = node?.parent as N; - isLeftChild = node === parent?.left; - } else { - if (!sibling) { - break; - } - - if (!sibling.right || sibling.right.color === RBColor.BLACK) { - // Case 3: Sibling is black, sibling's left child is red, and sibling's right child is black - sibling!.left!.color = RBColor.BLACK; - sibling.color = RBColor.RED; - this.rotateRight(sibling); - sibling = parent?.right as N; - } - - // Case 4: Sibling is black, sibling's right child is red - sibling.color = parent?.color as RBColor; - parent!.color = RBColor.BLACK; - sibling.right!.color = RBColor.BLACK; - this.rotateLeft(parent!); - node = this.root; - } - } else { - sibling = parent?.left as N; - - if (sibling?.color === RBColor.RED) { - // Case 1: Sibling is red, transform into a case where sibling is black - sibling.color = RBColor.BLACK; - parent!.color = RBColor.RED; - this.rotateRight(parent!); - sibling = parent!.left as N; - } - - if ( - (!sibling?.right || sibling.right.color === RBColor.BLACK) && - (!sibling?.left || sibling.left.color === RBColor.BLACK) - ) { - // Case 2: Sibling and both of its children are black - sibling.color = RBColor.RED; - node = parent; - parent = node?.parent as N; - isLeftChild = node === parent?.left; - } else { - if (!sibling) { - break; - } - - if (!sibling.left || sibling.left.color === RBColor.BLACK) { - // Case 3: Sibling is black, sibling's right child is red, and sibling's left child is black - sibling!.right!.color = RBColor.BLACK; - sibling.color = RBColor.RED; - this.rotateLeft(sibling); - sibling = parent!.left as N; - } - - // Case 4: Sibling is black, sibling's left child is red - sibling.color = parent?.color as RBColor; - parent!.color = RBColor.BLACK; - sibling.left!.color = RBColor.BLACK; - this.rotateRight(parent!); - node = this.root; - } - } - } - - if (node) { - node.color = RBColor.BLACK; - } - } - - - isRBTree(): boolean { - - if (this.root) { - const rootBlackHeight = this.computeBlackHeight(this.root); - return rootBlackHeight > 0; - } - - return true; - } - - private computeBlackHeight(node: N | null | undefined): number { - if (!node) { - - return 1; - } - - const leftHeight = this.computeBlackHeight(node.left); - const rightHeight = this.computeBlackHeight(node.right); - - if (leftHeight > 0 && rightHeight > 0 && leftHeight === rightHeight) { - return node.color === RBColor.BLACK ? leftHeight + 1 : leftHeight; - } else { - return 0; - } - } -======= // override add(keyOrNode: BTNKey | N | null, value?: V): N | null | undefined { // const inserted = super.add(keyOrNode, value); // if (inserted) this._fixInsertViolation(inserted); @@ -670,5 +355,4 @@ export class RBTree = RBTreeNode>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d } diff --git a/src/types/data-structures/binary-tree/binary-tree.ts b/src/types/data-structures/binary-tree/binary-tree.ts index b4afc49..c9da335 100644 --- a/src/types/data-structures/binary-tree/binary-tree.ts +++ b/src/types/data-structures/binary-tree/binary-tree.ts @@ -24,22 +24,7 @@ export enum FamilyPosition { export type BTNKey = number; -<<<<<<< HEAD:src/types/data-structures/binary-tree.ts -export type NodeOrPropertyName = 'node' | BinaryTreeNodePropertyName; - -export type DFSOrderPattern = 'in' | 'pre' | 'post'; - -export type BinaryTreeNodeKey = number; - -export type BinaryTreeNodeProperty> = - | N['val'] - | N - | number - | BinaryTreeNodeKey; -export type BinaryTreeDeletedResult = { deleted: N | null | undefined; needBalanced: N | null | undefined }; -======= export type BinaryTreeDeletedResult = { deleted: N | null | undefined; needBalanced: N | null }; ->>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d:src/types/data-structures/binary-tree/binary-tree.ts export type BinaryTreeNodeNested = BinaryTreeNode>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> diff --git a/test/unit/data-structures/binary-tree/rb-tree.test.ts b/test/unit/data-structures/binary-tree/rb-tree.test.ts index b159b3d..43d817f 100644 --- a/test/unit/data-structures/binary-tree/rb-tree.test.ts +++ b/test/unit/data-structures/binary-tree/rb-tree.test.ts @@ -1,47 +1,4 @@ import {RBTree, RBTreeNode} from '../../../../src'; -<<<<<<< HEAD - -describe('Red-Black Tree Tests', () => { - let tree: RBTree>; - - beforeEach(() => { - tree = new 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') - - 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); - expect(tree.has(3)).toBe(false); - - // Perform in-order traversal to check if the tree is still balanced - const inOrderTraversal: number[] = tree.dfs('in'); - console.log(inOrderTraversal) - - - expect(inOrderTraversal).toEqual([2, 4, 5, 6, 7, 8]); -======= describe('RBTreeNode', () => { it('should create an instance of RBTreeNode', () => { @@ -148,257 +105,5 @@ describe('Red-Black Tree Tests', () => { // // // expect(inOrderTraverse).toEqual([2, 4, 5, 6, 7, 8]); ->>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d }); }); - -describe('Red-Black Tree', () => { - let tree: RBTree>; - - beforeEach(() => { - tree = new RBTree>(); - }); - - it('should insert and retrieve values correctly', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - - expect(tree.get(10)).toBeDefined(); - expect(tree.get(20)).toBeDefined(); - expect(tree.get(5)).toBeDefined(); - expect(tree.get(15)).toBeDefined(); - expect(tree.get(30)).toBeUndefined(); - }); - - it('should remove values correctly', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(30); - tree.remove(20); - - expect(tree.get(20)).toBeUndefined(); - }); - - it('should perform in-order traversal', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - tree.add(30); - - const result: number[] = tree.dfs('in'); - - expect(result).toEqual([5, 10, 15, 20, 30]); - }); - - it('should validate red-black tree properties', () => { - tree.add(10); - tree.add(20); - tree.add(5); - tree.add(15); - - // expect(tree.isRBTree()).toBeTruthy(); - }); -}); - -describe('RBTree', () => { - let tree: RBTree; - - beforeEach(() => { - tree = new RBTree(); - }); - - test('should insert and find nodes correctly', () => { - tree.add(5); - tree.add(3); - tree.add(8); - - expect(tree.get(5)?.key).toBe(5); - expect(tree.get(3)?.key).toBe(3); - expect(tree.get(8)?.key).toBe(8); - }); - - test('should remove nodes correctly', () => { - tree.add(5); - tree.add(3); - tree.add(8); - - tree.remove(3); - expect(tree.get(3)).toBe(undefined); - - tree.remove(5); - expect(tree.get(5)).toBe(undefined); - - tree.remove(8); - expect(tree.get(8)).toBe(undefined); - }); - - test('should validate red-black tree properties', () => { - tree.add(5); - tree.add(3); - tree.add(8); - - expect(tree.isRBTree()).toBe(true); - expect(tree.isAVLBalanced()).toBe(true); - expect(tree.isPerfectlyBalanced()).toBe(true); - expect(tree.isEmpty()).toBe(false); - tree.remove(8); - expect(tree.size).toBe(2); - tree.remove(9); - expect(tree.size).toBe(2); - tree.remove(5); - expect(tree.size).toBe(1); - tree.remove(3); - expect(tree.size).toBe(0); - }); - - test('should handle various insert and remove scenarios', () => { - // Test your tree with various insertion and deletion scenarios - // and validate that it maintains red-black tree properties. - // Make sure to test both simple and complex cases. - - // For example: - tree.add(5); - tree.add(3); - tree.add(8); - tree.remove(3); - expect(tree.isRBTree()).toBe(true); - - // Add more test scenarios here. - }); -}); - -describe('RBTree', () => { - let tree: RBTree; - - beforeEach(() => { - tree = new RBTree(); - }); - - it('should add nodes and maintain RBTree properties', () => { - tree.add(10); - tree.add(5); - tree.add(15); - tree.add(3); - tree.add(7); - - // Make assertions here to check that the RBTree properties are maintained - // For example, check that there are no consecutive red nodes - }); - - it('should remove nodes and maintain RBTree properties', () => { - tree.add(10); - tree.add(5); - tree.add(15); - tree.add(3); - tree.add(7); - - tree.remove(5); - - // Make assertions here to check that the RBTree properties are maintained - }); - - it('should find nodes by key', () => { - tree.add(10, 'A'); - tree.add(5, 'B'); - tree.add(15, 'C'); - tree.add(3, 'D'); - tree.add(7, 'E'); - - const node = tree.get(5); - - expect(node?.val).toBe('B'); - }); - - it('should check RBTree properties', () => { - tree.add(10); - tree.add(5); - tree.add(15); - tree.add(3); - tree.add(7); - - const isRBTree = tree.isRBTree(); - - expect(isRBTree).toBe(true); - }); -}); - - - -describe('RBTree', () => { - it('should insert and find elements correctly', () => { - const tree = new RBTree>(); - - - tree.add(10); - tree.add(20); - tree.add(5); - - expect(tree.size).toBe(3); - expect(tree.get(10)?.key).toBe(10); - expect(tree.get(20)?.key).toBe(20); - expect(tree.get(5)?.key).toBe(5); - }); - - it('should delete elements correctly', () => { - const tree = new RBTree>(); - - - tree.add(10); - tree.add(20); - tree.add(5); - - tree.remove(10); - expect(tree.size).toBe(2); - expect(tree.get(10)).toBeUndefined(); - }); - - it('should balance the tree after insertions', () => { - const tree = new RBTree>(); - - - tree.add(10); - tree.add(20); - tree.add(5); - - // You can add expectations to check the tree's structure after insertions - // For example, checking that the root is black, and the leaves are black, etc. - }); - - it('should maintain Red-Black properties after deletions', () => { - const tree = new RBTree>(); - - tree.add(10); - tree.add(20); - tree.add(5); - - tree.remove(20); - - // You can add expectations to check Red-Black properties - // For example, checking that there are no two consecutive red nodes in a path, etc. - expect(tree.isRBTree()).toBe(true); - }); - - it('should handle edge cases', () => { - const tree = new RBTree>(); - - - // Test with an empty tree - expect(tree.size).toBe(0); - expect(tree.isRBTree()).toBe(true); - - // Test deleting non-existent elements - tree.add(10); - tree.remove(20); - expect(tree.size).toBe(1); - - // Test deleting the root element - tree.remove(10); - expect(tree.size).toBe(0); - }); -}); -