From 3c6da4d6c47f5f18a38b30cd4b0aa6271045dd25 Mon Sep 17 00:00:00 2001 From: LearnCodeZaid Date: Tue, 6 Oct 2026 16:56:10 +0530 Subject: [PATCH] fix(tree): set parent pointer in BinaryTreeNode.replaceChild replaceChild swapped the child pointer but never updated replacementNode.parent, leaving stale parent links after BST removal of a node with one child (issue 2102) and breaking any code walking parent pointers (issue 1102). Adds regression tests for both issues. Fixes trekhleb/javascript-algorithms#1102 Part of trekhleb/javascript-algorithms#2102 --- src/data-structures/tree/BinaryTreeNode.js | 2 ++ .../__test__/BinarySearchTree.test.js | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) 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 };