在二叉树中删除节点的操作相对于二叉搜索树来说稍微复杂一些,因为二叉树没有排序规则。删除节点的步骤如下:
-
首先,找到要删除的节点。可以使用递归或者迭代的方式进行查找。
-
如果要删除的节点是叶子节点(没有子节点),直接删除即可。
-
如果要删除的节点只有一个子节点,将子节点替代要删除的节点的位置。
-
如果要删除的节点有两个子节点,有两种方法可以选择:
- 找到要删除节点的后继节点(比要删除节点大的最小节点)或前驱节点(比要删除节点小的最大节点),将后继节点或前驱节点的值赋给要删除的节点,然后在右子树或左子树中递归地删除后继节点或前驱节点。
- 或者,可以选择找到要删除节点的左子树中的最大节点,将最大节点的值赋给要删除的节点,然后在左子树中递归地删除最大节点。
以下是一个使用C++实现二叉树删除节点的示例代码:
#include <iostream>
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int value) : val(value), left(nullptr), right(nullptr) {}
};
TreeNode* insert(TreeNode* root, int value) {
if (root == nullptr) {
return new TreeNode(value);
}
if (root->left == nullptr) {
root->left = insert(root->left, value);
} else {
root->right = insert(root->right, value);
}
return root;
}
TreeNode* findNode(TreeNode* root, int value) {
if (root == nullptr || root->val == value) {
return root;
}
TreeNode* left = findNode(root->left, value);
if (left != nullptr) {
return left;
}
TreeNode* right = findNode(root->right, value);
if (right != nullptr) {
return right;
}
return nullptr;
}
void deleteNode(TreeNode* root, int value) {
if (root == nullptr) {
return;
}
TreeNode* nodeToDelete = findNode(root, value);
if (nodeToDelete == nullptr) {
return;
}
// 找到要删除节点的父节点
TreeNode* parent = nullptr;
TreeNode* current = root;
while (current != nullptr && current != nodeToDelete) {
parent = current;
if (value < current->val) {
current = current->left;
} else {
current = current->right;
}
}
// 如果要删除的节点是叶子节点
if (nodeToDelete->left == nullptr && nodeToDelete->right == nullptr) {
if (parent != nullptr) {
if (parent->left == nodeToDelete) {
parent->left = nullptr;
} else {
parent->right = nullptr;
}
} else {
root = nullptr;
}
delete nodeToDelete;
}
// 如果要删除的节点只有一个子节点
else if (nodeToDelete->left == nullptr || nodeToDelete->right == nullptr) {
TreeNode* child = (nodeToDelete->left != nullptr) ? nodeToDelete->left : nodeToDelete->right;
if (parent != nullptr) {
if (parent->left == nodeToDelete) {
parent->left = child;
} else {
parent->right = child;
}
} else {
root = child;
}
delete nodeToDelete;
}
// 如果要删除的节点有两个子节点
else {
TreeNode* successor = nodeToDelete->right;
TreeNode* successorParent = nodeToDelete;
while (successor->left != nullptr) {
successorParent = successor;
successor = successor->left;
}
nodeToDelete->val = successor->val;
if (successorParent->left == successor) {
successorParent->left = successor->right;
} else {
successorParent->right = successor->right;
}
delete successor;
}
}
void inorderTraversal(TreeNode* root) {
if (root == nullptr) {
return;
}
inorderTraversal(root->left);
std::cout << root->val << " ";
inorderTraversal(root->right);
}
int main() {
TreeNode* root = nullptr;
root = insert(root, 5);
root = insert(root, 3);
root = insert(root, 6);
root = insert(root, 2);
root = insert(root, 4);
root = insert(root, 7);
std::cout << "Inorder traversal before deletion: ";
inorderTraversal(root);
std::cout << std::endl;
deleteNode(root, 3);
std::cout << "Inorder traversal after deletion: ";
inorderTraversal(root);
std::cout << std::endl;
return 0;
}
在这个示例中,我们定义了一个TreeNode
结构体表示二叉树的节点。我们使用insert
函数向二叉树中插入节点,并使用findNode
函数查找要删除的节点。
在deleteNode
函数中,我们首先找到要删除的节点及其父节点。然后根据要删除的节点的子节点情况,进行相应的删除操作。如果要删除的节点是叶子节点,直接删除即可。如果要删除的节点只有一个子节点,将子节点替代要删除的节点的位置。如果要删除的节点有两个子节点,我们选择找到要删除节点的后继节点,将后继节点的值赋给要删除的节点,然后在右子树中递归地删除后继节点。
在main
函数中,我们创建一个二叉树,并进行中序遍历来验证树的结构。然后我们删除值为3的节点,并再次进行中序遍历来验证删除操作是否成功。
输出结果为:
Inorder traversal before deletion: 2 3 4 5 6 7
Inorder traversal after deletion: 2 4 5 6 7
这表示在删除值为3的节点后,二叉树的中序遍历结果为2 4 5 6 7。
希望对你有帮助!