mirror of
https://github.com/krahets/hello-algo.git
synced 2025-11-03 05:27:55 +08:00
Free memory after removing
a node from a LinkedList or TreeNode.
This commit is contained in:
@ -293,6 +293,8 @@ comments: true
|
||||
ListNode* P = n0->next;
|
||||
ListNode* n1 = P->next;
|
||||
n0->next = n1;
|
||||
// 释放内存
|
||||
delete P;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -331,7 +331,10 @@ comments: true
|
||||
int poll() {
|
||||
int num = peek();
|
||||
// 删除头结点
|
||||
ListNode *tmp = front;
|
||||
front = front->next;
|
||||
// 释放内存
|
||||
delete tmp;
|
||||
queSize--;
|
||||
return num;
|
||||
}
|
||||
|
||||
@ -311,7 +311,10 @@ comments: true
|
||||
/* 出栈 */
|
||||
int pop() {
|
||||
int num = top();
|
||||
ListNode *tmp = stackTop;
|
||||
stackTop = stackTop->next;
|
||||
// 释放内存
|
||||
delete tmp;
|
||||
stkSize--;
|
||||
return num;
|
||||
}
|
||||
|
||||
@ -772,7 +772,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
node = child;
|
||||
} else {
|
||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
||||
TreeNode temp = minNode(node.right);
|
||||
TreeNode temp = getInOrderNext(node.right);
|
||||
node.right = removeHelper(node.right, temp.val);
|
||||
node.val = temp.val;
|
||||
}
|
||||
@ -783,16 +783,6 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
// 返回子树的根节点
|
||||
return node;
|
||||
}
|
||||
|
||||
/* 获取最小结点 */
|
||||
TreeNode minNode(TreeNode node) {
|
||||
if (node == null) return node;
|
||||
// 循环访问左子结点,直到叶结点时为最小结点,跳出
|
||||
while (node.left != null) {
|
||||
node = node.left;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@ -828,22 +818,13 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
else:
|
||||
node = child
|
||||
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.val = temp.val
|
||||
# 更新结点高度
|
||||
self.__update_height(node)
|
||||
# 2. 执行旋转操作,使该子树重新恢复平衡
|
||||
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"
|
||||
@ -904,7 +885,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
else
|
||||
{
|
||||
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点
|
||||
TreeNode? temp = minNode(node.right);
|
||||
TreeNode? temp = getInOrderNext(node.right);
|
||||
node.right = removeHelper(node.right, temp.val);
|
||||
node.val = temp.val;
|
||||
}
|
||||
@ -915,18 +896,6 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
||||
// 返回子树的根节点
|
||||
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` 替换待删除结点;
|
||||
|
||||
=== "Step 1"
|
||||
|
||||

|
||||
|
||||
=== "Step 2"
|
||||
|
||||

|
||||
|
||||
=== "Step 3"
|
||||
|
||||

|
||||
|
||||
=== "Step 4"
|
||||
|
||||

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