Skip to content

Instantly share code, notes, and snippets.

@pengdu
Created August 8, 2023 10:21
Show Gist options
  • Save pengdu/8281da4dcf730f13142808620dbf9552 to your computer and use it in GitHub Desktop.
Save pengdu/8281da4dcf730f13142808620dbf9552 to your computer and use it in GitHub Desktop.
chatgpt在二叉树中删除节点

在二叉树中删除节点的操作相对于二叉搜索树来说稍微复杂一些,因为二叉树没有排序规则。删除节点的步骤如下:

  1. 首先,找到要删除的节点。可以使用递归或者迭代的方式进行查找。

  2. 如果要删除的节点是叶子节点(没有子节点),直接删除即可。

  3. 如果要删除的节点只有一个子节点,将子节点替代要删除的节点的位置。

  4. 如果要删除的节点有两个子节点,有两种方法可以选择:

    • 找到要删除节点的后继节点(比要删除节点大的最小节点)或前驱节点(比要删除节点小的最大节点),将后继节点或前驱节点的值赋给要删除的节点,然后在右子树或左子树中递归地删除后继节点或前驱节点。
    • 或者,可以选择找到要删除节点的左子树中的最大节点,将最大节点的值赋给要删除的节点,然后在左子树中递归地删除最大节点。

以下是一个使用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。

希望对你有帮助!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment