二叉搜索树基本操作(BST)

定义

typedef struct node{
    int key;
    node* p = NULL; //存储其父结点
    node* left = NULL; //存储其左子结点
    node* right = NULL; //存储其右子结点
}Node;

搜索操作

Node* BST_Search(Node* node, int k)
{
    if (node == NULL || node->key == k) return node; //树为空 或 根结点即为要找的结点
    if(node->key > k) return BST_Search(node -> left, k); //查找左子树
    else return BST_Search(node -> right, k); //查找右子树
}

返回最小值/最大值结点

Node* BST_minimum(Node* node) //两个操作是对称的
{
    while(node -> left != NULL)
        node = node -> left;
    return node;
}
Node* BST_maximum(Node* node)
{
    while (node -> right != NULL)
        node = node -> right;
    return node;
}

中序遍历

void in_order_search(Node* node)
{
    if(node != NULL)
    {
        in_order_search(node->left); //先搜索左子树
        cout << node -> key; //再搜素根节点
        in_order_search(node -> right); //最后搜索右子树
    }
}

返回一个结点的后继

一个结点的后续(successor)为关键字大于当前结点的最小结点

Node* BST_successor(Node* node) //与返回前驱的操作对称
{
    // 若传入根节点但没有右子节点 则其为最大关键字 返回NULL
    // 一个结点的前驱可能在右子树(如果该结点存在右子结点)即右子树中的最小结点
    // 也可能在祖宗结点上(不存在右子结点)即路径上第一个大于该结点的祖宗结点
    if(node -> right != NULL)
        return BST_minimum(node -> right);
    Node* par = node->p;
    while(par != NULL && node == par->right)
    {
        node = par;
        par = par -> p;
    }
    return par;
}

返回一个结点的前驱

Node* BST_predecessor(Node* node)
{
    // 若传入根节点但没有右子节点 则其为最小关键字 返回NULL
    if(node -> left != NULL)
        return BST_maximum(node -> left);
    Node* par = node->p;
    while(par != NULL && node == par -> left)
    {
        node = par;
        par = par -> p;
    }
    return par;
}

插入结点

void BST_insert(Node* &root, Node* z)
{
    // 从根结点出发寻找合适插入该结点的叶结点位置
    // 换句话说,插入操作一定是插入在叶结点上(由二叉树的性质知道这是一定可以做到的)
    // 因为一定存在一种偏序关系使新结点可以不断"下沉"
    Node* y = NULL;
    Node* x = root; 
    while(x != NULL)
    {
        y = x;
        if(z -> key < x -> key)
            x = x -> left;
        else
            x = x -> right;
    }
    if(y == NULL) root = z; // 说明为空树
    else if (z -> key < y -> key) y->left = z; // 作为 y 的左子结点
    else y -> right = z; // 作为 y 的右子结点
}

取代操作(删除操作中会用到)

void BST_transplant(Node* &root, Node* u, Node* v) //用 v 取代 u
{
    if(u -> p == NULL) root = v;
    else if (u == u->p->left) u->p->left = v;
    else u->p->right = v;
    if(v != NULL)
        v->p = u->p;
}

删除操作

void BST_delete(Node* root, Node* z)
{
    // 无子结点直接删除即可
    // 前两个分支分别处理只有一个子结点的情况,这个时候删除可以直接用子结点替代上来
    if(z->left == NULL)
        BST_transplant(root, z, z->right);
    else if(z->right == NULL)
        BST_transplant(root, z, z->left);
    else // 处理两个结点都存在的情况
    {   // 最后要用后继结点 y 来替代 才不会违反BST的性质
        Node* y = BST_minimum(z->right);
        // 若后继 y 不是 z 的右子结点 那么要先将 y 的右子树替代 y 
        // 后继 y 是不可能存在左子树的(否则真正的后继应该在为 y 的左子树中)
        if(y->p != z)
        {
            BST_transplant(root, y, y->right);
            y->right = z->right; // 将 y 结点接到 z 的右子结点之上 使其化为下面这种情况
            y->right->p = y;
        }
        // 处理后继 y 结点直接就是 z 的右子结点的情况
        BST_transplant(root, z, y); //直接用 y 取代 z 即可
        y->left = z->left;
        y->left->p = y;
    }
}

参考资料:Introduction to Algorithm, Third Edition, Chapter 12 Binary search tree.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值