二叉搜索树

来源:互联网 发布:网页数据库查询系统 编辑:程序博客网 时间:2024/05/20 09:25

二叉搜索树是在二叉树的基础上的根据子树的值的大小进行了排序调整后的结果,而且它是红黑树的基础结构,在了解红黑树之前学习二叉搜索树对后面掌握红黑树是有很大帮助的。

定义

二叉树的任意结点,它的左子树关键字不超过父结点,右子树关键字不小于父结点,则这样的二叉树成为二叉搜索树。

查找

相对于普通二叉树的查找,二叉搜索树可以借助待查数与当前结点的相对大小确定下一步搜索的方向。
查找代码的递归版本:

Node search(Node node,int value){    if(node==null){        return;    }    if(node.value==value){        return node;    }    if(value<node.value){        return search(node.lChild,value);    }    if(value>node.value){        return search(node.rChild,value);    }}

非递归版本代码:

Node search(Node node,int value){    if(node==null){        return;    }    while(node.value!=value&&node!=null){        if(value<node.value){            node=node.lChild;        }        if(value>node.value){            node=node.rChild;        }    }    return node;}

插入

二叉搜索树的插入操作和查找很类似,直接看代码
递归版插入伪代码:

void insert(Node node,int value){    if(node==null){        if(node.p!=null){//node.p表示node父结点            if(node.p.value<value){                node.rChild.value=value;            }else{                node.lChild.value=value;            }        }        return;    }    if(value>node.value){        insert(node.rChild,value);    }    if(value<node.value){        insert(node.lChild,value);    }}

非递归的代码

void insert(Node node,int value){    if(node==null){        return;    }    while(node!=null){        temp=node;//暂存下node,作为插入结点的父结点        if(value<node.value){            node=node.lChild;        }else{            node=node.rChild;        }    }    if(temp.value>value){        temp.lChild.value=value;    }else{        temp.rChild.value=value;    }}

删除

二叉查找树的删除分三种情况考虑(假设要删除的结点是z):

  • z是叶子结点,直接删除,并将z在父结点的子树位置空
  • z只有一个孩子结点,直接将孩子结点放置到z的位置,修改z在父结点的子树位置为z的孩子结点
  • z有两个孩子结点,找到z的后继结点y,让y占据原来z的位置,z的左右子树分别称为y的左右子树。该情况还得再分为y是否为z的右孩子。

如下图所示:
这里写图片描述
后继结点是指二叉查找树中从小到大排序后,排在删除结点的后一个的结点,也就是中序遍历时,访问删除结点后下一个要访问的结点,所以访问z之后,再访问z的右子树,如果右子树的左子树为空,则访问右子树的根结点,否则访问右子树的最左子结点。所以说第三种删除情况又分为两种情况:图(a)中,y代替z,z原来的左子树成为y的左子树,y原来的右子树仍作为y的右子树,z结点删除;图(b)中,y结点代替z结点,z原来的左子树作为y的左子树,y原来的 右子树作为y原来的父结点的左子树,z结点删除。
可以看到,四种情况下,都包含有将某个节点的整个子树替换原来的结点操作(第一种情况可理解成空子树替换原来的结点)。先给出某结点替换另一结点的统一操作注意,替换操作,只是调整了old点的父结点,并没有调整new点的左右子树指向old点左右指数,因为四种情况,子树的调整上并不完全统一

void replace(Node root,Node old,Node new){    if(old.p==null){//考虑原来的结点是头结点        root=new;    }    if(old.p.lChild!=null){        old.p.lChild=new;    }else{        old.p.rChild=new;    }    if(new!=null){//父结点指向子结点之后,子结点也需要指向父结点        new.p=old.p;    }}

从上述代码看出,old为root结点,new为null结点等特殊情况下,均可以实现new替换old的操作。
有了replace方法,我们写delete方法就方便了,代码如下:

void delete(Node root,Node z){    if(root==null||z==null){        return;    }    if(z.lChild==null&&z.rChild==null){//删除叶子结点        replace(root,z,null);    }else if(z.lChild==null&&z.rChild!=null){//只有右子树        replace(root,z,z.rChild);    }else if(z.rChild=null&&z.lChild!=null){//只有左子树        replace(root,z.z.lChild);    }else{//左右子树均不为空        //找中继结点        Node y=z.rChild;        while(y!=null){            y=y.lChild;        }        if(y.p==z){//中继结点就是z的右孩子            replace(root,z,y);            y.lChild=z.lChild;//调整y新的左子树            y.lChild.p=y;        }else{//中继结点是z的右孩子的最左孩子            replace(root,y,y.rChild);//先用y的右孩子替换y            y.rChild=z.rChild;//调整y和z.rChild            y.rChild.p=y;            replace(root,z,y);            y.lChild=z.lChild;//调整y新的左子树            y.lChild.p=y;        }        //关于中继结点对应的if/else,可以优化成        //  if(y.p!=z){        //  replace(root,y,y.rChild);//先用y的右孩子替换y        //  y.rChild=z.rChild;//调整y和z.rChild        //  y.rChild.p=y;        //  }        //  replace(root,z,y);        //  y.lChild=z.lChild;//调整y新的左子树        //  y.lChild.p=y;        //博主个人觉得不优化的时候适合初学者理解,理解了之后再优化成这样,也是好理解的。    }}

优化的过程相当于下图所示:
这里写图片描述
图(a)表示第三种情况的第一种可能,图(b)表示第三种情况的第二种可能。此时可以将图(b)的中继结点先调整到位,构成图(a)的样子,然后再和图(a)一样replace(root,z,y),所以如果第二种情况,就多执行如下几步即可。

if(y.p!=z){
replace(root,y,y.rChild);//先用y的右孩子替换y
y.rChild=z.rChild;//调整y和z.rChild
y.rChild.p=y;
}

总结

关于二叉搜索树的常见操作就说完了, 下篇文章我们分析二叉搜索树的升级版红黑树。
本文主要参考《算法导论——第三版》第12章。
很惭愧,做了一点微小的贡献!

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 盆栽金银花叶子全部落掉怎么办 荷花竹根部烂了怎么办 水培绿萝叶子发黄怎么办 大早上的公鸡老打鸣怎么办 紫吊兰叶子变绿怎么办 芙桑花叶子发黄怎么办 长春花长得太高怎么办 四季梅叶子蔫了怎么办 吸财树叶子蔫了怎么办 民族团结手抄报间单有漂亮怎么办 鹦鹉尾巴毛掉了怎么办 羊绒衫领子打太大了怎么办 内裤洗了还有一股味道怎么办 月经下不来内裤上总有脏东西怎么办 夏天外衣薄露出内衣怎么办 金毛体味很重怎么办 直筒连衣裙太短怎么办 托班社会下雨了怎么办 托班下雨了怎么办教案 吃鸡界面有鼠标怎么办 老年机成英语了怎么办 手机成了英语了怎么办 塑料袋融化粘到衣服上怎么办 厕所被卫生纸堵了怎么办 钻石画的胶不粘了怎么办 客厅沙发选大了怎么办 连衣裙腰大了怎么办呀 憋尿后出现尿急尿涨怎么办 脚有酸酸的味道怎么办 三星手机home键失灵怎么办 三星s6返回键失灵怎么办 三星s7屏幕漏液怎么办 三星s8出现蓝框怎么办 三星手机短信图标没了怎么办 ps没有足够的ram怎么办 ps性能调不了是怎么办 苹果6p照相模糊怎么办 相框玻璃碎了怎么办 word文档加密后忘记密码怎么办 手机wps密码忘了怎么办 苹果手表忘了密码怎么办