Free memory after removing

a node from a LinkedList or TreeNode.
pull/200/head
Yudong Jin 2 years ago
parent 6b02449f22
commit 410c5d6b62

@ -21,6 +21,8 @@ void remove(ListNode* n0) {
ListNode* P = n0->next; ListNode* P = n0->next;
ListNode* n1 = P->next; ListNode* n1 = P->next;
n0->next = n1; n0->next = n1;
// 释放内存
delete P;
} }
/* 访问链表中索引为 index 的结点 */ /* 访问链表中索引为 index 的结点 */

@ -50,7 +50,10 @@ public:
int poll() { int poll() {
int num = peek(); int num = peek();
// 删除头结点 // 删除头结点
ListNode *tmp = front;
front = front->next; front = front->next;
// 释放内存
delete tmp;
queSize--; queSize--;
return num; return num;
} }

@ -39,7 +39,10 @@ public:
/* 出栈 */ /* 出栈 */
int pop() { int pop() {
int num = top(); int num = top();
ListNode *tmp = stackTop;
stackTop = stackTop->next; stackTop = stackTop->next;
// 释放内存
delete tmp;
stkSize--; stkSize--;
return num; return num;
} }

@ -96,11 +96,13 @@ public:
// 删除结点 cur // 删除结点 cur
if (pre->left == cur) pre->left = child; if (pre->left == cur) pre->left = child;
else pre->right = child; else pre->right = child;
// 释放内存
delete cur;
} }
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode* nex = min(cur->right); TreeNode* nex = getInOrderNext(cur->right);
int tmp = nex->val; int tmp = nex->val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex->val); remove(nex->val);
@ -110,8 +112,8 @@ public:
return cur; return cur;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
TreeNode* min(TreeNode* root) { TreeNode* getInOrderNext(TreeNode* root) {
if (root == nullptr) return root; if (root == nullptr) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root->left != nullptr) { while (root->left != nullptr) {

@ -33,6 +33,7 @@ int main() {
PrintUtil::printTree(n1); PrintUtil::printTree(n1);
// 删除结点 P // 删除结点 P
n1->left = n2; n1->left = n2;
delete P; // 释放内存
cout << endl << "删除结点 P 后\n" << endl; cout << endl << "删除结点 P 后\n" << endl;
PrintUtil::printTree(n1); PrintUtil::printTree(n1);

@ -162,7 +162,7 @@ namespace hello_algo.chapter_tree
else else
{ {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode? temp = minNode(node.right); TreeNode? temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
@ -174,8 +174,8 @@ namespace hello_algo.chapter_tree
return node; return node;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
private TreeNode? minNode(TreeNode? node) private TreeNode? getInOrderNext(TreeNode? node)
{ {
if (node == null) return node; if (node == null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出

@ -125,7 +125,7 @@ namespace hello_algo.chapter_tree
else else
{ {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode? nex = min(cur.right); TreeNode? nex = getInOrderNext(cur.right);
if (nex != null) if (nex != null)
{ {
int tmp = nex.val; int tmp = nex.val;
@ -138,8 +138,8 @@ namespace hello_algo.chapter_tree
return cur; return cur;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
private TreeNode? min(TreeNode? root) private TreeNode? getInOrderNext(TreeNode? root)
{ {
if (root == null) return root; if (root == null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出

@ -23,13 +23,13 @@ func NewBinarySearchTree(nums []int) *BinarySearchTree {
} }
} }
// GetRoot Get the root node of binary search tree /* 获取根结点 */
func (bst *BinarySearchTree) GetRoot() *TreeNode { func (bst *BinarySearchTree) GetRoot() *TreeNode {
return bst.root return bst.root
} }
// GetMin Get node with the min value /* 获取中序遍历的下一个结点 */
func (bst *BinarySearchTree) GetMin(node *TreeNode) *TreeNode { func (bst *BinarySearchTree) GetInOrderNext(node *TreeNode) *TreeNode {
if node == nil { if node == nil {
return node return node
} }
@ -40,19 +40,6 @@ func (bst *BinarySearchTree) GetMin(node *TreeNode) *TreeNode {
return node return node
} }
// GetInorderNext Get node inorder next
func (bst *BinarySearchTree) GetInorderNext(node *TreeNode) *TreeNode {
if node == nil || node.Right == nil {
return node
}
node = node.Right
// 循环访问左子结点,直到叶结点时为最小结点,跳出
for node.Left != nil {
node = node.Left
}
return node
}
/* 查找结点 */ /* 查找结点 */
func (bst *BinarySearchTree) Search(num int) *TreeNode { func (bst *BinarySearchTree) Search(num int) *TreeNode {
node := bst.root node := bst.root
@ -149,7 +136,7 @@ func (bst *BinarySearchTree) Remove(num int) *TreeNode {
// 子结点数为 2 // 子结点数为 2
} else { } else {
// 获取中序遍历中待删除结点 cur 的下一个结点 // 获取中序遍历中待删除结点 cur 的下一个结点
next := bst.GetInorderNext(cur) next := bst.GetInOrderNext(cur)
temp := next.Val temp := next.Val
// 递归删除结点 next // 递归删除结点 next
bst.Remove(next.Val) bst.Remove(next.Val)

@ -12,33 +12,30 @@ import (
func TestBinarySearchTree(t *testing.T) { func TestBinarySearchTree(t *testing.T) {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
bst := NewBinarySearchTree(nums) bst := NewBinarySearchTree(nums)
fmt.Println("初始化的二叉树为:") fmt.Println("\n初始化的二叉树为:")
bst.Print() bst.Print()
// 获取根结点 // 获取根结点
node := bst.GetRoot() node := bst.GetRoot()
fmt.Println("二叉树的根结点为:", node.Val) fmt.Println("\n二叉树的根结点为:", node.Val)
// 获取最小的结点
node = bst.GetMin(bst.GetRoot())
fmt.Println("二叉树的最小结点为:", node.Val)
// 查找结点 // 查找结点
node = bst.Search(5) node = bst.Search(5)
fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val) fmt.Println("\n查找到的结点对象为", node, ",结点值 =", node.Val)
// 插入结点 // 插入结点
node = bst.Insert(16) node = bst.Insert(16)
fmt.Println("插入结点后 16 的二叉树为:") fmt.Println("\n插入结点后 16 的二叉树为:")
bst.Print() bst.Print()
// 删除结点 // 删除结点
bst.Remove(1) bst.Remove(1)
fmt.Println("删除结点 1 后的二叉树为:") fmt.Println("\n删除结点 1 后的二叉树为:")
bst.Print() bst.Print()
bst.Remove(2) bst.Remove(2)
fmt.Println("删除结点 2 后的二叉树为:") fmt.Println("\n删除结点 2 后的二叉树为:")
bst.Print() bst.Print()
bst.Remove(4) bst.Remove(4)
fmt.Println("删除结点 4 后的二叉树为:") fmt.Println("\n删除结点 4 后的二叉树为:")
bst.Print() bst.Print()
} }

@ -138,7 +138,7 @@ class AVLTree {
node = child; node = child;
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode temp = minNode(node.right); TreeNode temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
@ -150,8 +150,8 @@ class AVLTree {
return node; return node;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
private TreeNode minNode(TreeNode node) { private TreeNode getInOrderNext(TreeNode node) {
if (node == null) return node; if (node == null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出
while (node.left != null) { while (node.left != null) {

@ -101,7 +101,7 @@ class BinarySearchTree {
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode nex = min(cur.right); TreeNode nex = getInOrderNext(cur.right);
int tmp = nex.val; int tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
@ -111,8 +111,8 @@ class BinarySearchTree {
return cur; return cur;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
public TreeNode min(TreeNode root) { public TreeNode getInOrderNext(TreeNode root) {
if (root == null) return root; if (root == null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root.left != null) { while (root.left != null) {

@ -98,7 +98,7 @@ function remove(num) {
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
let nex = min(cur.right); let nex = getInOrderNext(cur.right);
let tmp = nex.val; let tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
@ -108,8 +108,8 @@ function remove(num) {
return cur; return cur;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
function min(root) { function getInOrderNext(root) {
if (root === null) return root; if (root === null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root.left !== null) { while (root.left !== null) {

@ -132,7 +132,7 @@ class AVLTree:
else: else:
node = child node = child
else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
temp = self.__min_node(node.right) temp = self.__get_inorder_next(node.right)
node.right = self.__remove_helper(node.right, temp.val) node.right = self.__remove_helper(node.right, temp.val)
node.val = temp.val node.val = temp.val
# 更新结点高度 # 更新结点高度
@ -140,8 +140,8 @@ class AVLTree:
# 2. 执行旋转操作,使该子树重新恢复平衡 # 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node) return self.__rotate(node)
""" 获取最小结点 """ """ 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def __min_node(self, node: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]: def __get_inorder_next(self, node: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
if node is None: if node is None:
return None return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出 # 循环访问左子结点,直到叶结点时为最小结点,跳出

@ -117,7 +117,7 @@ class BinarySearchTree:
# 子结点数量 = 2 # 子结点数量 = 2
else: else:
# 获取中序遍历中 cur 的下一个结点 # 获取中序遍历中 cur 的下一个结点
nex = self.min(cur.right) nex = self.get_inorder_next(cur.right)
tmp = nex.val tmp = nex.val
# 递归删除结点 nex # 递归删除结点 nex
self.remove(nex.val) self.remove(nex.val)
@ -125,11 +125,10 @@ class BinarySearchTree:
cur.val = tmp cur.val = tmp
return cur return cur
""" 获取最小结点 """ """ 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """
def min(self, root: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]: def get_inorder_next(self, root: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
if root is None: if root is None:
return root return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出 # 循环访问左子结点,直到叶结点时为最小结点,跳出
while root.left is not None: while root.left is not None:
root = root.left root = root.left

@ -120,7 +120,7 @@ function remove(num: number): TreeNode | null {
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
let next = min(cur.right); let next = getInOrderNext(cur.right);
let tmp = next!.val; let tmp = next!.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(next!.val); remove(next!.val);
@ -130,8 +130,8 @@ function remove(num: number): TreeNode | null {
return cur; return cur;
} }
/* 获取最小结点 */ /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */
function min(root: TreeNode | null): TreeNode | null { function getInOrderNext(root: TreeNode | null): TreeNode | null {
if (root === null) { if (root === null) {
return null; return null;
} }

@ -293,6 +293,8 @@ comments: true
ListNode* P = n0->next; ListNode* P = n0->next;
ListNode* n1 = P->next; ListNode* n1 = P->next;
n0->next = n1; n0->next = n1;
// 释放内存
delete P;
} }
``` ```

@ -331,7 +331,10 @@ comments: true
int poll() { int poll() {
int num = peek(); int num = peek();
// 删除头结点 // 删除头结点
ListNode *tmp = front;
front = front->next; front = front->next;
// 释放内存
delete tmp;
queSize--; queSize--;
return num; return num;
} }

@ -311,7 +311,10 @@ comments: true
/* 出栈 */ /* 出栈 */
int pop() { int pop() {
int num = top(); int num = top();
ListNode *tmp = stackTop;
stackTop = stackTop->next; stackTop = stackTop->next;
// 释放内存
delete tmp;
stkSize--; stkSize--;
return num; return num;
} }

@ -772,7 +772,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
node = child; node = child;
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode temp = minNode(node.right); TreeNode temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
@ -783,16 +783,6 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
// 返回子树的根节点 // 返回子树的根节点
return node; return node;
} }
/* 获取最小结点 */
TreeNode minNode(TreeNode node) {
if (node == null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (node.left != null) {
node = node.left;
}
return node;
}
``` ```
=== "C++" === "C++"
@ -828,22 +818,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
else: else:
node = child node = child
else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
temp = self.min_node(node.right) temp = self.__get_inorder_next(node.right)
node.right = self.__remove_helper(node.right, temp.val) node.right = self.__remove_helper(node.right, temp.val)
node.val = temp.val node.val = temp.val
# 更新结点高度 # 更新结点高度
self.__update_height(node) self.__update_height(node)
# 2. 执行旋转操作,使该子树重新恢复平衡 # 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node) return self.__rotate(node)
""" 获取最小结点 """
def min_node(self, node: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
if node is None:
return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出
while node.left is not None:
node = node.left
return node
``` ```
=== "Go" === "Go"
@ -904,7 +885,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
else else
{ {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
TreeNode? temp = minNode(node.right); TreeNode? temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
@ -915,18 +896,6 @@ AVL 树的独特之处在于「旋转 Rotation」的操作其可 **在不影
// 返回子树的根节点 // 返回子树的根节点
return node; return node;
} }
/* 获取最小结点 */
private TreeNode? minNode(TreeNode? node)
{
if (node == null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (node.left != null)
{
node = node.left;
}
return node;
}
``` ```
### 查找结点 ### 查找结点

@ -445,19 +445,15 @@ comments: true
3. 使用 `nex` 替换待删除结点; 3. 使用 `nex` 替换待删除结点;
=== "Step 1" === "Step 1"
![bst_remove_case3_1](binary_search_tree.assets/bst_remove_case3_1.png) ![bst_remove_case3_1](binary_search_tree.assets/bst_remove_case3_1.png)
=== "Step 2" === "Step 2"
![bst_remove_case3_2](binary_search_tree.assets/bst_remove_case3_2.png) ![bst_remove_case3_2](binary_search_tree.assets/bst_remove_case3_2.png)
=== "Step 3" === "Step 3"
![bst_remove_case3_3](binary_search_tree.assets/bst_remove_case3_3.png) ![bst_remove_case3_3](binary_search_tree.assets/bst_remove_case3_3.png)
=== "Step 4" === "Step 4"
![bst_remove_case3_4](binary_search_tree.assets/bst_remove_case3_4.png) ![bst_remove_case3_4](binary_search_tree.assets/bst_remove_case3_4.png)
删除结点操作也使用 $O(\log n)$ 时间,其中查找待删除结点 $O(\log n)$ ,获取中序遍历后继结点 $O(\log n)$ 。 删除结点操作也使用 $O(\log n)$ 时间,其中查找待删除结点 $O(\log n)$ ,获取中序遍历后继结点 $O(\log n)$ 。
@ -489,11 +485,13 @@ comments: true
// 删除结点 cur // 删除结点 cur
if (pre.left == cur) pre.left = child; if (pre.left == cur) pre.left = child;
else pre.right = child; else pre.right = child;
// 释放内存
delete cur;
} }
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode nex = min(cur.right); TreeNode nex = getInOrderNext(cur.right);
int tmp = nex.val; int tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
@ -502,15 +500,6 @@ comments: true
} }
return cur; return cur;
} }
/* 获取最小结点 */
TreeNode min(TreeNode root) {
if (root == null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root.left != null) {
root = root.left;
}
return root;
}
``` ```
=== "C++" === "C++"
@ -544,7 +533,7 @@ comments: true
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode* nex = min(cur->right); TreeNode* nex = getInOrderNext(cur->right);
int tmp = nex->val; int tmp = nex->val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex->val); remove(nex->val);
@ -553,15 +542,6 @@ comments: true
} }
return cur; return cur;
} }
/* 获取最小结点 */
TreeNode* min(TreeNode* root) {
if (root == nullptr) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root->left != nullptr) {
root = root->left;
}
return root;
}
``` ```
=== "Python" === "Python"
@ -604,23 +584,13 @@ comments: true
# 子结点数量 = 2 # 子结点数量 = 2
else: else:
# 获取中序遍历中 cur 的下一个结点 # 获取中序遍历中 cur 的下一个结点
nex = self.min(cur.right) nex = self.get_inorder_next(cur.right)
tmp = nex.val tmp = nex.val
# 递归删除结点 nex # 递归删除结点 nex
self.remove(nex.val) self.remove(nex.val)
# 将 nex 的值复制给 cur # 将 nex 的值复制给 cur
cur.val = tmp cur.val = tmp
return cur return cur
""" 获取最小结点 """
def min(self, root: typing.Optional[TreeNode]) -> typing.Optional[TreeNode]:
if root is None:
return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出
while root.left is not None:
root = root.left
return root
``` ```
=== "Go" === "Go"
@ -671,7 +641,7 @@ comments: true
// 子结点数为 2 // 子结点数为 2
} else { } else {
// 获取中序遍历中待删除结点 cur 的下一个结点 // 获取中序遍历中待删除结点 cur 的下一个结点
next := bst.GetInorderNext(cur) next := bst.GetInOrderNext(cur)
temp := next.Val temp := next.Val
// 递归删除结点 next // 递归删除结点 next
bst.Remove(next.Val) bst.Remove(next.Val)
@ -713,7 +683,7 @@ comments: true
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
let nex = min(cur.right); let nex = getInOrderNext(cur.right);
let tmp = nex.val; let tmp = nex.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(nex.val); remove(nex.val);
@ -766,7 +736,7 @@ comments: true
// 子结点数量 = 2 // 子结点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
let next = min(cur.right); let next = getInOrderNext(cur.right);
let tmp = next!.val; let tmp = next!.val;
// 递归删除结点 nex // 递归删除结点 nex
remove(next!.val); remove(next!.val);
@ -824,7 +794,7 @@ comments: true
else else
{ {
// 获取中序遍历中 cur 的下一个结点 // 获取中序遍历中 cur 的下一个结点
TreeNode? nex = min(cur.right); TreeNode? nex = getInOrderNext(cur.right);
if (nex != null) if (nex != null)
{ {
int tmp = nex.val; int tmp = nex.val;
@ -836,18 +806,6 @@ comments: true
} }
return cur; return cur;
} }
/* 获取最小结点 */
TreeNode? min(TreeNode? root)
{
if (root == null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root.left != null)
{
root = root.left;
}
return root;
}
``` ```
## 二叉搜索树的优势 ## 二叉搜索树的优势

Loading…
Cancel
Save