c#数据结构之二叉搜索树(BST)

本文详细介绍了二叉搜索树(BST)的特点,包括节点的键值关系以及中序遍历的性质。同时,展示了BST中查找、插入和删除操作的递归实现,包括找到目标节点、新增节点以及删除指定节点的逻辑流程。这些基本操作对于理解BST的数据结构和算法至关重要。

特点

  • 节点的左子树仅包含键小于节点键的节点。
  • 节点的右子树仅包含键大于节点键的节点。
  • 左右子树也必须是二叉搜索树。

事实

  • BST 的中序遍历总是产生排序的输出。
  • 通过对唯一给定的遍历进行排序来获得中序遍历。

查找

public Node search(Node root,
                   int key)
{
    if (root == null ||
        root.key == key)
        return root;
 
    if (root.key < key)
       return search(root.right, key);
 
    return search(root.left, key);
}

插入

 Node insertRec(Node root, int key)
{
    if (root == null) {
        root = new Node(key);
        return root;
    }

    if (key < root.key)
        root.left = insertRec(root.left, key);
    else if (key > root.key)
        root.right = insertRec(root.right, key);

    return root;
}

删除

Node deleteRec(Node root, int key)
{
    if (root == null)
        return root;

    if (key < root.key)
        root.left = deleteRec(root.left, key);
    else if (key > root.key)
        root.right = deleteRec(root.right, key);
    else {
        if (root.left == null)
            return root.right;
        else if (root.right == null)
            return root.left;

        root.key = minValue(root.right);

        root.right = deleteRec(root.right, root.key);
    }
    return root;
}

int minValue(Node root)
{
    int minv = root.key;
    while (root.left != null) {
        minv = root.left.key;
        root = root.left;
    }
    return minv;
}
### 删除二搜索树 (BST) 中的节点 在二搜索树中删除一个节点是一个较为复杂的操作,因为它不仅涉及找到目标节点并将其移除,还需要保持 BST 的性质不变。以下是关于如何实现这一功能的具体方法: #### 1. 查找要删除的目标节点 首先需要通过比较 `key` 和当前节点的值来定位到待删除的节点位置。如果 `key` 小于当前节点,则向左子树继续查找;反之则向右子树查找。 #### 2. 处理三种可能的情况 一旦找到了目标节点,根据其结构特性会有以下几种情况处理方式: - **情况一:目标节点无任何子节点** 如果该节点既没有左孩子也没有右孩子,那么可以直接将父节点指向它的指针置为空即可完成删除操作[^1]。 - **情况二:目标节点只有一个子节点** 当目标节点仅有一个子节点时(无论是左侧还是右侧),只需让这个唯一的子节点替代原节点的位置,从而维持整个树形结构以及 BST 性质。 - **情况三:目标节点有两个子节点** 这是最复杂的一种情形。此时需寻找此节点的后继者或者前驱者作为替换对象: - 后继者定义为目标节点右子树中最左边的那个叶子节点; - 前驱者则是左子树最右边那个叶子节点。 找到合适的替身之后,用它覆盖掉原来的数据域内容,并随后对该替身上执行一次递归调用来真正意义上把它从新调整后的树里清除出去。 ```cpp TreeNode* deleteNode(TreeNode* root, int key){ if (!root) return nullptr; if (key < root->val){ root->left = deleteNode(root->left, key); } else if(key > root->val){ root->right = deleteNode(root->right, key); }else{ // 叶子结点 或 单独一侧有孩子的简单情况 if(!root->left && !root->right) {return NULL;} if(!root->left || !root->right){ TreeNode *temp = root->left ? root->left : root->right; free(root); return temp; } // 寻找最小的大于本节点的数值(即右子树中的最小值) TreeNode* minRightSubtree = findMin(root->right); root->val = minRightSubtree->val; // 继续删除minRightSubtree所在位置上的重复项 root->right = deleteNode(root->right,minRightSubtree->val); } return root; } // 辅助函数用于获取某个节点下的最小值 TreeNode* findMin(TreeNode* node){ while(node&&node->left !=NULL){ node=node->left; } return node; } ``` 以上代码展示了 C++ 实现版本的一个典型例子,其中包含了完整的逻辑链条以应对各种不同类型的删除需求[^3]。 #### 注意事项 尽管理论上可以通过上述算法有效实施删除动作,但在实际应用过程中还需注意一些细节问题比如内存管理等问题以免造成资源泄漏等情况发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值