From b39e79be85c868250473916b4f48a9f8162126a3 Mon Sep 17 00:00:00 2001 From: krahets Date: Fri, 26 May 2023 20:34:22 +0800 Subject: [PATCH] Fix remove() in binary search tree. --- codes/cpp/chapter_tree/binary_search_tree.cpp | 13 +++-- .../csharp/chapter_tree/binary_search_tree.cs | 56 +++++++++++++------ .../dart/chapter_tree/binary_search_tree.dart | 14 +++-- codes/go/chapter_tree/binary_search_tree.go | 14 +++-- .../java/chapter_tree/binary_search_tree.java | 13 +++-- .../chapter_tree/binary_search_tree.js | 9 ++- .../python/chapter_tree/binary_search_tree.py | 20 ++++--- .../chapter_tree/binary_search_tree.swift | 11 +++- .../chapter_tree/binary_search_tree.ts | 11 +++- 9 files changed, 111 insertions(+), 50 deletions(-) diff --git a/codes/cpp/chapter_tree/binary_search_tree.cpp b/codes/cpp/chapter_tree/binary_search_tree.cpp index 3df23fc3f..195a1a1ce 100644 --- a/codes/cpp/chapter_tree/binary_search_tree.cpp +++ b/codes/cpp/chapter_tree/binary_search_tree.cpp @@ -112,10 +112,15 @@ class BinarySearchTree { // 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点 TreeNode *child = cur->left != nullptr ? cur->left : cur->right; // 删除节点 cur - if (pre->left == cur) - pre->left = child; - else - pre->right = child; + if (cur != root) { + if (pre->left == cur) + pre->left = child; + else + pre->right = child; + } else { + // 若删除节点为根节点,则重新指定根节点 + root = child; + } // 释放内存 delete cur; } diff --git a/codes/csharp/chapter_tree/binary_search_tree.cs b/codes/csharp/chapter_tree/binary_search_tree.cs index 577c26a18..88bd9fe65 100644 --- a/codes/csharp/chapter_tree/binary_search_tree.cs +++ b/codes/csharp/chapter_tree/binary_search_tree.cs @@ -21,13 +21,15 @@ class BinarySearchTree { /* 构建二叉搜索树 */ public TreeNode? buildTree(int[] nums, int i, int j) { - if (i > j) return null; + if (i > j) + return null; // 将数组中间节点作为根节点 int mid = (i + j) / 2; TreeNode root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 root.left = buildTree(nums, i, mid - 1); root.right = buildTree(nums, mid + 1, j); + return root; } @@ -37,11 +39,14 @@ class BinarySearchTree { // 循环查找,越过叶节点后跳出 while (cur != null) { // 目标节点在 cur 的右子树中 - if (cur.val < num) cur = cur.right; + if (cur.val < num) cur = + cur.right; // 目标节点在 cur 的左子树中 - else if (cur.val > num) cur = cur.left; + else if (cur.val > num) + cur = cur.left; // 找到目标节点,跳出循环 - else break; + else + break; } // 返回目标节点 return cur; @@ -50,24 +55,30 @@ class BinarySearchTree { /* 插入节点 */ public void insert(int num) { // 若树为空,直接提前返回 - if (root == null) return; + if (root == null) + return; TreeNode? cur = root, pre = null; // 循环查找,越过叶节点后跳出 while (cur != null) { // 找到重复节点,直接返回 - if (cur.val == num) return; + if (cur.val == num) + return; pre = cur; // 插入位置在 cur 的右子树中 - if (cur.val < num) cur = cur.right; + if (cur.val < num) + cur = cur.right; // 插入位置在 cur 的左子树中 - else cur = cur.left; + else + cur = cur.left; } // 插入节点 TreeNode node = new TreeNode(num); if (pre != null) { - if (pre.val < num) pre.right = node; - else pre.left = node; + if (pre.val < num) + pre.right = node; + else + pre.left = node; } } @@ -75,29 +86,38 @@ class BinarySearchTree { /* 删除节点 */ public void remove(int num) { // 若树为空,直接提前返回 - if (root == null) return; + if (root == null) + return; TreeNode? cur = root, pre = null; // 循环查找,越过叶节点后跳出 while (cur != null) { // 找到待删除节点,跳出循环 - if (cur.val == num) break; + if (cur.val == num) + break; pre = cur; // 待删除节点在 cur 的右子树中 - if (cur.val < num) cur = cur.right; + if (cur.val < num) + cur = cur.right; // 待删除节点在 cur 的左子树中 - else cur = cur.left; + else + cur = cur.left; } // 若无待删除节点,则直接返回 - if (cur == null || pre == null) return; + if (cur == null || pre == null) + return; // 子节点数量 = 0 or 1 if (cur.left == null || cur.right == null) { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode? child = cur.left != null ? cur.left : cur.right; // 删除节点 cur - if (pre.left == cur) { - pre.left = child; + if (cur != root) { + if (pre.left == cur) + pre.left = child; + else + pre.right = child; } else { - pre.right = child; + // 若删除节点为根节点,则重新指定根节点 + root = child; } } // 子节点数量 = 2 diff --git a/codes/dart/chapter_tree/binary_search_tree.dart b/codes/dart/chapter_tree/binary_search_tree.dart index acc5c3e6d..6ae7f5958 100644 --- a/codes/dart/chapter_tree/binary_search_tree.dart +++ b/codes/dart/chapter_tree/binary_search_tree.dart @@ -104,10 +104,16 @@ void remove(int num) { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode? child = cur.left ?? cur.right; // 删除节点 cur - if (pre!.left == cur) - pre.left = child; - else - pre.right = child; + if (cur != root) { + if (pre!.left == cur) + pre.left = child; + else + pre.right = child; + } else { + // 若删除节点为根节点,则重新指定根节点 + root = child; + } + } else { // 子节点数量 = 2 // 获取中序遍历中 cur 的下一个节点 diff --git a/codes/go/chapter_tree/binary_search_tree.go b/codes/go/chapter_tree/binary_search_tree.go index 6cb6554e7..624bd3cfa 100644 --- a/codes/go/chapter_tree/binary_search_tree.go +++ b/codes/go/chapter_tree/binary_search_tree.go @@ -128,12 +128,18 @@ func (bst *binarySearchTree) remove(num int) { } else { child = cur.Right } - // 将子节点替换为待删除节点 - if pre.Left == cur { - pre.Left = child + // 删除节点 cur + if cur != bst.root { + if pre.Left == cur { + pre.Left = child + } else { + pre.Right = child + } } else { - pre.Right = child + // 若删除节点为根节点,则重新指定根节点 + bst.root = child } + // 子节点数为 2 } else { // 获取中序遍历中待删除节点 cur 的下一个节点 diff --git a/codes/java/chapter_tree/binary_search_tree.java b/codes/java/chapter_tree/binary_search_tree.java index 314659668..2abc445e1 100644 --- a/codes/java/chapter_tree/binary_search_tree.java +++ b/codes/java/chapter_tree/binary_search_tree.java @@ -109,10 +109,15 @@ class BinarySearchTree { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode child = cur.left != null ? cur.left : cur.right; // 删除节点 cur - if (pre.left == cur) - pre.left = child; - else - pre.right = child; + if (cur != root) { + if (pre.left == cur) + pre.left = child; + else + pre.right = child; + } else { + // 若删除节点为根节点,则重新指定根节点 + root = child; + } } // 子节点数量 = 2 else { diff --git a/codes/javascript/chapter_tree/binary_search_tree.js b/codes/javascript/chapter_tree/binary_search_tree.js index a222d1f36..601770d15 100644 --- a/codes/javascript/chapter_tree/binary_search_tree.js +++ b/codes/javascript/chapter_tree/binary_search_tree.js @@ -95,8 +95,13 @@ function remove(num) { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur.left !== null ? cur.left : cur.right; // 删除节点 cur - if (pre.left === cur) pre.left = child; - else pre.right = child; + if (cur != root) { + if (pre.left === cur) pre.left = child; + else pre.right = child; + } else { + // 若删除节点为根节点,则重新指定根节点 + root = child; + } } // 子节点数量 = 2 else { diff --git a/codes/python/chapter_tree/binary_search_tree.py b/codes/python/chapter_tree/binary_search_tree.py index 0c16f5059..209cc0833 100644 --- a/codes/python/chapter_tree/binary_search_tree.py +++ b/codes/python/chapter_tree/binary_search_tree.py @@ -43,7 +43,7 @@ class BinarySearchTree: def search(self, num: int) -> TreeNode | None: """查找节点""" - cur: TreeNode | None = self.__root + cur: TreeNode | None = self.root # 循环查找,越过叶节点后跳出 while cur is not None: # 目标节点在 cur 的右子树中 @@ -60,11 +60,11 @@ class BinarySearchTree: def insert(self, num: int) -> None: """插入节点""" # 若树为空,直接提前返回 - if self.__root is None: + if self.root is None: return # 循环查找,越过叶节点后跳出 - cur, pre = self.__root, None + cur, pre = self.root, None while cur is not None: # 找到重复节点,直接返回 if cur.val == num: @@ -87,11 +87,11 @@ class BinarySearchTree: def remove(self, num: int) -> None: """删除节点""" # 若树为空,直接提前返回 - if self.__root is None: + if self.root is None: return # 循环查找,越过叶节点后跳出 - cur, pre = self.__root, None + cur, pre = self.root, None while cur is not None: # 找到待删除节点,跳出循环 if cur.val == num: @@ -112,10 +112,14 @@ class BinarySearchTree: # 当子节点数量 = 0 / 1 时, child = null / 该子节点 child = cur.left or cur.right # 删除节点 cur - if pre.left == cur: - pre.left = child + if cur != self.root: + if pre.left == cur: + pre.left = child + else: + pre.right = child else: - pre.right = child + # 若删除节点为根节点,则重新指定根节点 + self.__root = cur # 子节点数量 = 2 else: # 获取中序遍历中 cur 的下一个节点 diff --git a/codes/swift/chapter_tree/binary_search_tree.swift b/codes/swift/chapter_tree/binary_search_tree.swift index 874d0c509..f0be742ca 100644 --- a/codes/swift/chapter_tree/binary_search_tree.swift +++ b/codes/swift/chapter_tree/binary_search_tree.swift @@ -123,10 +123,15 @@ class BinarySearchTree { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur?.left != nil ? cur?.left : cur?.right // 删除节点 cur - if pre?.left === cur { - pre?.left = child + if cur != root { + if pre?.left === cur { + pre?.left = child + } else { + pre?.right = child + } } else { - pre?.right = child + // 若删除节点为根节点,则重新指定根节点 + root = cur; } } // 子节点数量 = 2 diff --git a/codes/typescript/chapter_tree/binary_search_tree.ts b/codes/typescript/chapter_tree/binary_search_tree.ts index d2fbf2de6..8a08caa18 100644 --- a/codes/typescript/chapter_tree/binary_search_tree.ts +++ b/codes/typescript/chapter_tree/binary_search_tree.ts @@ -110,10 +110,15 @@ function remove(num: number): void { // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur.left !== null ? cur.left : cur.right; // 删除节点 cur - if (pre!.left === cur) { - pre!.left = child; + if (cur != root) { + if (pre!.left === cur) { + pre!.left = child; + } else { + pre!.right = child; + } } else { - pre!.right = child; + // 若删除节点为根节点,则重新指定根节点 + root = child; } } // 子节点数量 = 2