diff --git a/src/data-structures/tree/BinaryTreeNode.js b/src/data-structures/tree/BinaryTreeNode.js index 44c9390e41..b04b065290 100644 --- a/src/data-structures/tree/BinaryTreeNode.js +++ b/src/data-structures/tree/BinaryTreeNode.js @@ -167,11 +167,13 @@ export default class BinaryTreeNode { if (this.left && this.nodeComparator.equal(this.left, nodeToReplace)) { this.left = replacementNode; + replacementNode.parent = this; return true; } if (this.right && this.nodeComparator.equal(this.right, nodeToReplace)) { this.right = replacementNode; + replacementNode.parent = this; return true; } diff --git a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js index 105f94b0b5..0ae92f37f0 100644 --- a/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js +++ b/src/data-structures/tree/binary-search-tree/__test__/BinarySearchTree.test.js @@ -1,4 +1,5 @@ import BinarySearchTree from '../BinarySearchTree'; +import BinarySearchTreeNode from '../BinarySearchTreeNode'; describe('BinarySearchTree', () => { it('should create binary search tree', () => { @@ -52,6 +53,28 @@ describe('BinarySearchTree', () => { expect(removed2).toBe(true); }); + it('should keep parent pointers consistent when removing a node with one child (issue #2102)', () => { + const root = new BinarySearchTreeNode(8); + root.insert(3); + root.insert(6); + root.remove(3); + root.remove(6); + expect(root.right).toBeNull(); + expect(root.left).toBeNull(); + }); + + it('should re-parent the surviving child via replaceChild (issue #1102)', () => { + const bst = new BinarySearchTree(); + bst.insert(10); + bst.insert(5); + bst.insert(3); + const node5 = bst.root.left; + bst.remove(5); + expect(bst.root.left.value).toBe(3); + expect(bst.root.left.parent).toBe(bst.root); + expect(node5.parent).toBeNull(); + }); + it('should insert object values', () => { const nodeValueCompareFunction = (a, b) => { const normalizedA = a || { value: null };