二叉排序树的插入、删除实现(C++)

二叉排序树的插入、删除实现

二叉排序树的结构体声明:

struct TreeNode {
    int val;
    TreeNode *left; // 左节点
    TreeNode *right; // 右节点
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

二叉排序树的插入操作

二叉排序树的插入操作,本质上和查找类似,通过递归很容易实现:

void insert(TreeNode*& root, int v){
    // 向 根节点为 root 的树插入 数据 v
    if (root == nullptr) {
        root = new TreeNode(v);
        return ;
    }
    if (root->val < v) {
        insert(root->right, v);
    }else if (root->val > v) {
        insert(root->left, v);
    } else {
        return ;
    }
    return ;
}

二叉排序树的删除操作

二叉排序树的删除操作更为复杂一些:

  1. 如果当前节点是叶子节点,可以直接删除。
  2. 如果当前节点只有左子树或者只有右子树,直接使用子节点替换当前节点即可。
  3. 如果当前节点既有左子树又有右子树,应当让右子树的最左下方节点替换它。
    代码实现:
void deleteV(TreeNode*& root,int v){
    // 向 根节点为 root 的树插入 数据 v
    if (root == nullptr) {
        cout << "删除节点失败!" << endl;
        return;
    }
    if (root->val < v) {
        deleteV(root->right, v);
    }else if (root->val > v) {
        deleteV(root->left, v);
    }else {
        if (root->left == nullptr && root->right == nullptr)
            root = nullptr, delete root; // 如果左右子树都为空,直接删除该节点
        else if (root->left && root->right) { // 如果左右子树都存在
            // 查找中序排序的下一个节点
            TreeNode* nxtTreeNode;
            nxtTreeNode = root->right;
            while (nxtTreeNode->left)
                nxtTreeNode = nxtTreeNode->left;
            // 交换两个节点的值
            swap(nxtTreeNode->val, root->val);
            deleteV(root->right, v);
        } else if (root->left) { // 左不为空, 右为空
            TreeNode* tmp = root;
            root = root->left;
            delete tmp;
        } else { // 左为空,右不为空
            TreeNode* tmp = root;
            root = root->right;
            delete tmp; 
        }
    }
    return ;
}

代码测试

void preOrder(TreeNode* root){
    if (root == nullptr) return;
    cout << root->val << ", ";
    preOrder(root->left);
    preOrder(root->right);
}
void inOrder(TreeNode* root){
    if (root == nullptr) return;
    inOrder(root->left);
    cout << root->val << ", ";
    inOrder(root->right);
}

int main(){
    vector<int> nums{53, 78, 65, 94, 81, 88, 17, 9, 45, 23};
    TreeNode* root = nullptr;
    for (int num : nums) {
        insert(root, num);
    }
    cout << "preOrder: ";
    preOrder(root);
    cout << endl;
    cout << "inOrder: ";
    inOrder(root);
    cout << endl;
    deleteV(root, 78);
    cout << "preOrder: ";
    preOrder(root);
    cout << endl;
    cout << "inOrder: ";
    inOrder(root);
    cout << endl;
    return 0;
}

测试结果

preOrder: 53, 17, 9, 45, 23, 78, 65, 94, 81, 88
inOrder: 9, 17, 23, 45, 53, 65, 78, 81, 88, 94
preOrder: 53, 17, 9, 45, 23, 81, 65, 94, 88
inOrder: 9, 17, 23, 45, 53, 65, 81, 88, 94

完整代码

#include<bits/stdc++.h>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left; // 左节点
    TreeNode *right; // 右节点
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
void insert(TreeNode*& root, int v){
    // 向 根节点为 root 的树插入 数据 v
    if (root == nullptr) {
        root = new TreeNode(v);
        return ;
    }
    if (root->val < v) {
        insert(root->right, v);
    }else if (root->val > v) {
        insert(root->left, v);
    } else {
        return ;
    }
    return ;
}
void deleteV(TreeNode*& root,int v){
    // 向 根节点为 root 的树插入 数据 v
    if (root == nullptr) {
        cout << "删除节点失败!" << endl;
        return;
    }
    if (root->val < v) {
        deleteV(root->right, v);
    }else if (root->val > v) {
        deleteV(root->left, v);
    }else {
        if (root->left == nullptr && root->right == nullptr)
            root = nullptr, delete root; // 如果左右子树都为空,直接删除该节点
        else if (root->left && root->right) { // 如果左右子树都存在
            // 查找中序排序的下一个节点
            TreeNode* nxtTreeNode;
            nxtTreeNode = root->right;
            while (nxtTreeNode->left)
                nxtTreeNode = nxtTreeNode->left;
            // 交换两个节点的值
            swap(nxtTreeNode->val, root->val);
            deleteV(root->right, v);
        } else if (root->left) { // 左不为空, 右为空
            TreeNode* tmp = root;
            root = root->left;
            delete tmp;
        } else { // 左为空,右不为空
            TreeNode* tmp = root;
            root = root->right;
            delete tmp; 
        }
    }
    return ;
}
void preOrder(TreeNode* root){
    if (root == nullptr) return;
    cout << root->val << ", ";
    preOrder(root->left);
    preOrder(root->right);
}
void inOrder(TreeNode* root){
    if (root == nullptr) return;
    inOrder(root->left);
    cout << root->val << ", ";
    inOrder(root->right);
}

int main(){
    vector<int> nums{53, 78, 65, 94, 81, 88, 17, 9, 45, 23};
    TreeNode* root = nullptr;
    for (int num : nums) {
        insert(root, num);
    }
    cout << "preOrder: ";
    preOrder(root);
    cout << endl;
    cout << "inOrder: ";
    inOrder(root);
    cout << endl;
    deleteV(root, 78);
    cout << "preOrder: ";
    preOrder(root);
    cout << endl;
    cout << "inOrder: ";
    inOrder(root);
    cout << endl;
    return 0;
}

从以上测试结果来看,代码应当没有很大的问题,可放心食用~
创作不易,欢迎点赞,感谢~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值