二叉搜索树(查找,插入,删除)

动态查找:集合是动态变化的 ,除查找,还可能发生插入和删除

二叉搜索树为例:

//结构如下:
typedef struct binary_tree* tree;
struct binary_tree{
    elementtype data;
    tree left;
    tree right;
};

二叉搜索树定义:一棵二叉树,可以为空;如果不为空,满足以下性质:

  1. 非空左子树的所有键值小于其根结点的键值。

  2. 非空右子树的所有键值大于其根结点的键值。

  3. 左、右子树都是二叉搜索树。

  • 查找:(返回x节点,失败返回NULL)

    ------------------查找元素X的位置----------------
    //尾递归:
    tree find(elementtype x,tree bt) 
    { 
    if( !bt ) return NULL; /*查找失败*/ 
    if( x > bt->data )  
        return find(x,bt->right); /*在右子树中继续查找*/ 
    else if( x < bt->data )  
        return find(x,bt->left); /*在左子树中继续查找*/ 
    else 
        return bt; /*查找成功,返回结点的地址*/ 
    } 
    
    //由于非递归函数的执行效率高,下面将尾递归改为迭代:
    tree find(elementtype x,tree bt){
        while(bt){
            if (x>bt->data) bt=bt->right;	/*向右子树中移动,继续查找*/
            else if (x<bt->data) bt=bt->left;	/*向左子树中移动,继续查找*/
            else return bt;	/*查找成功,返回找到结点的地址*/
        }
        return NULL;	/*查找失败*/
    }
    
    ------------------查找最小元素的位置----------------
    tree find_min(tree bt){
        if (bt)
            while (bt->left) bt=bt->left;
        return bt;
    }
    
    ------------------查找最大元素的位置----------------
    tree find_max(tree bt){
        if (bt)
            while (bt->right) bt=bt->right;	//沿右分支继续查找,直到最右叶结点
        return bt;
    }
    
  • 插入:(返回结果树根节点)

    tree insert(elementtype x,tree bt){
        if (!bt){	/*若原树为空,生成并返回一个结点的二叉搜索树*/
            bt=(tree)malloc(sizeof(struct binary_tree));
            bt->data=x;
            bt->left=bt->right=NULL;
            return bt;
        }
        else{	/*开始找要插入元素的位置*/
            tree top=bt;
            int flag=0;	//判断在left插入还是right插入
            tree temp=NULL;	//记录父节点
            while (bt){
                temp=bt;
                if (x>bt->data){	//右子树寻找插入位置
                    bt=bt->right;
                    flag=1;
                }
                else if (x<bt->data){	//左子树寻找插入位置
                    bt=bt->left;
                    flag=0;
                }
                else return true;	//x已存在,直接返回插入成功
            }
            if (flag){	//flag==1,在temp的right下新建节点
                temp->right=(tree)malloc(sizeof(struct binary_tree));
                temp->right->data=x;
                temp->rigth->left=temp->right->right=NULL;
            }
            else{	//flag==0,在temp的left下新建节点
                temp->left=(tree)malloc(sizeof(struct binary_tree));
                temp->left->data=x;
                temp->left->left=temp->left->right=NULL;
            }
            return top;
        }
    }
    
  • 删除:(返回结果树根节点)

    //递归:
    tree delete(elementtype x,tree bt){
        if (!bt) reeturn NULL;	//空树
        else if (x<bt->data) bt->left=delete(x,bt->left);//左子树递归删除
        else if (x>bt->data) bt->right=delete(x,bt->right);//右子树递归删除 
        else{	//找到要删除的结点
            tree temp=NULL;
            if (bt->left && bt->right){	//待删除节点有左,右子树
                //在右子树中找最小的元素填充删除结点
                temp=find_min(bt->right);
                bt->data=temp->data;
                bt->right=delete(bt->data,bt->right);
            }
            else{	//待删除节点仅有左子树,或仅有右子树,或无子节点
                temp=bt;
                if (bt->left)	//有左节点
                    bt=bt->left;
                else	//有右节点,或无子节点
                    bt=bt->right;
                free(temp);
            }
        }
        return bt;
    }
    //非递归:(稍微复杂一些)
    tree delete(elementtype x,tree bt){
        if (!bt) reeturn NULL;	//空树
        
        tree top=bt;	//记录根节点
        tree parent=bt;	//记录父节点
        while(bt){	//寻找x位置
            if (x>bt->data){
                parent=bt;
                bt=bt->right;
            }
            else if (x<bt->data){
                parent=bt;
                bt=bt->left;
            }
            else break;	//找到,退出循环
        }
        if (!bt) return top;	//未找到
        
        if (bt->left && bt->right){	//待删除节点有左,右子树
            tree temp=bt->right;	//在右子树中找最小的元素填充删除结点
            while(temp->left){
                parent=temp;
                temp=temp->left;
            }
            bt->data=temp->data;
            if (temp==parent->right)//说明待删除节点的右子树为斜右二叉树(包括一个节点情况)
                parent->right=temp->right;
            else
                parent->left=temp->right;//待删除节点的右子节点有左子树
            free(temp);
            return top;
        }
        else{	//待删除节点仅有左子树,或仅有右子树,或无子节点
            tree temp=bt;
            if (parent==bt){	//删除根节点(包括最后一个节点情况)
                if (bt->left) bt=bt->left;
                else bt=bt->right;
                free(temp);
                return bt;
            }
            else{	//根节点不变
                if (bt==parent->left){
                    if (bt->left) parent->left=bt->left;
            		else parent-left=bt->right;
                }
                else{
                    if (bt->left) parent->right=bt->left;
            		else parent->right=bt->right;
                }
            	free(temp);
                return top;
            }
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值