[rbtree branch] conflicts resolved

This commit is contained in:
Revone 2023-10-31 11:38:54 +08:00
parent cc3be9349f
commit 7b0dddc69e
4 changed files with 0 additions and 631 deletions

View file

@ -231,10 +231,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
* @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<C extends BTNCallback<N>>(
identifier: ReturnType<C> | null,
callback: C = ((node: N) => node.key) as C,
@ -242,7 +238,6 @@ export class BST<V = any, N extends BSTNode<V, N> = BSTNode<V, BSTNodeNested<V>>
iterationType = this.iterationType
): N | null {
return this.getNodes(identifier, callback, true, beginRoot, iterationType)[0] ?? null;
>>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d
}
/**

View file

@ -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<V, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNest
return new RBTreeNode(key, value) as N;
}
<<<<<<< HEAD
override add(key: BinaryTreeNodeKey, val?: N['val']): N {
const newNode = this.createNode(key, val);
if (!this.root) {
this._setRoot(newNode);
newNode.color = RBColor.BLACK;
} else {
this.insertNode(this.root, newNode);
this.fixInsertViolations(newNode);
}
this._setSize(this.size + 1);
return newNode;
}
private insertNode(root: N, node: N): void {
if (node.key < root.key) {
if (!root.left) {
root.left = node;
node.parent = root;
} else {
this.insertNode(root.left as N, node);
}
} else if (node.key > 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<N>[] {
const result: BinaryTreeDeletedResult<N>[] = [];
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<V, N extends RBTreeNode<V, N> = RBTreeNode<V, RBTreeNodeNest
//
// return parent;
// }
>>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d
}

View file

@ -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 extends BinaryTreeNode<N['val'], N>> =
| N['val']
| N
| number
| BinaryTreeNodeKey;
export type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined; needBalanced: N | null | undefined };
=======
export type BinaryTreeDeletedResult<N> = { deleted: N | null | undefined; needBalanced: N | null };
>>>>>>> 10bbcffcef4ed5901867431a3d3eae891d190b9d:src/types/data-structures/binary-tree/binary-tree.ts
export type BinaryTreeNodeNested<T> = BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, BinaryTreeNode<T, any>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

View file

@ -1,47 +1,4 @@
import {RBTree, RBTreeNode} from '../../../../src';
<<<<<<< HEAD
describe('Red-Black Tree Tests', () => {
let tree: RBTree<RBTreeNode<number>>;
beforeEach(() => {
tree = new 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]);
});
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<RBTreeNode<number>>;
beforeEach(() => {
tree = new RBTree<RBTreeNode<number>>();
});
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<RBTreeNode<number>>();
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<RBTreeNode<number>>();
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<RBTreeNode<number>>();
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<RBTreeNode<number>>();
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<RBTreeNode<number>>();
// 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);
});
});