二叉排序树的插入和删除操作

简介: 二叉排序树的插入和删除操作

公众号merlinsea


  • 二叉排序树介绍
  • 二叉排序树是一棵二叉树或者空树
  • 若它的左子树不空,则左子树的所有节点的关键字均小于根节点
  • 若它的右子树不空,则右子树的所有节点的关键字均大于根节点

640.png

  • 二叉排序树的插入操作
  • 插入操作是指向一个二叉排序树中插入一个元素,如果这个元素已经存在,则插入失败;如果不存在则插入成功。
  • 插入操作结束后仍旧需要保证这个二叉排序树的左小右大的特点。
  • 比如向上面这个二叉排序树中插入元素6,这个元素6最后会插入在节点5的右孩子处。

  • 插入操作——代码实现


/ 返回true代表插入成功,返回false代表插入失败
    public boolean insert(BTNode p){
        if(p==null){
            return false;
        }
        if(root==null){
            root = p;
        }else{
            //工作节点
            BTNode work = root;
            while(work!=null){
                if(work.val < p.val){
                    //p应该插入在work的右边
                    if(work.right!=null){
                        work = work.right;
                    }else{
                        //完成了插入;
                        work.right = p;
                        break;
                    }
                }else if(work.val > p.val){
                    //p应该插入在work的左边
                    if(work.left != null){
                        work = work.left;
                    }else{
                        //完成插入插入操作
                        work.left = p;
                        break;
                    }
                }else{
                    //我们找到了一个一抹一样的节点,更新info信息,返回fasle
                    work.info = p.info;
                    return false;
                }
            }
        }
        return true;
    }


  • 二叉排序树的查询操作
  • 查询操作就是从树的根节点出发,查找知道关键值的元素,如果可以找到则返回这个元素,如果不可以找到则返回空。
  • 查询操作的代码实现


public BTNode find(int val){
        BTNode p = root;
        while(p!=null){
            if(p.val == val){
                break;
            }else if(p.val < val){
                //说明目标节点在p的右边
                p = p.right;
            }else{
                //说明目标节点在p的左边
                p = p.left;
            }
        }
        return p;
    }


  • 二叉排序树的删除操作
  • 删除操作是指需要在一棵二叉排序树中删除指定关键字的节点,同样的删除以后需要保证二叉排序树的左小右大的特征。
  • 二叉排序树删除的三种情况
  • 删除的是叶子节点,即待删除元素左右子树都为空的情况,直接删除即可。
  • 删除的是单分支的节点,即待删除元素左子树为空右子树不为空 或者 右子树为空左子树不为空,只需要讲其孩子节点来替代这个待删除的节点即可。
  • 删除的是双分支节点,即待删除的元素左右子树都不空的情况,可以将其左子树中的最大值来替换当前节点,同时删除左子树中的最大值,或者可以将其右子树中的最小值来替换当前节点,同时删除右子树中的最小值。
  • 删除节点的时候,我们需要找到待删除目标节点的父节点,比如下图中我们需要删除节点4,我们需要找到4的父节点5,让5的左指针指向2。

640.png


  • 删除操作代码实现


public boolean delete(int val){
        //1、先找到待删除元素的父节点
        BTNode target = findDel(val);
        if(target==null){
            // 说明查找失败
            return false;
        }
        //2、删除元素 ---> 根节点 / 非根节点
        //左子树的最大值来填充
        if(val == root.val){
            //说明删除的是根节点
            if(root.left == null && root.right ==null){
                root = null;
            }else if(root.left == null){
                root = root.right;
            }else if(root.right == null){
                root = root.left;
            }else{
                //寻找左子树最大值
                BTNode p = root.left;
                while(p.right != null){
                    p = p.right;
                }
                delete(p.val);
                root.val = p.val;
                root.info = p.info;
            }
        }else{
            //说明删除的不是根节点,则target是待删除元素的父亲节点
            if(target.left!=null && target.left.val == val){
                //说明需要删除的是target的左节点
                BTNode del = target.left;
                if(del.left == null && del.right == null){
                    target.left = null;
                }else if(del.left == null){
                    target.left = del.right;
                }else if(del.right == null){
                    target.left = del.left;
                }else{
                    //说明待删除元素有左右孩子节点
                    BTNode p = del.left;
                    while(p.right!=null){
                        p = p.right;
                    }
                    delete(p.val);
                    del.val = p.val;
                    del.info = p.info;
                }
            }else{
                //说明待删除的是target的右孩子
                BTNode del = target.right;
                if(del.left == null && del.right == null){
                    target.right = null;
                }else if(del.left == null){
                    target.right = del.right;
                }else if(del.right == null){
                    target.right = del.left;
                }else{
                    //说明待删除元素有左右孩子节点
                    BTNode p = del.left;
                    while(p.right!=null){
                        p = p.right;
                    }
                    delete(p.val);
                    del.val = p.val;
                    del.info = p.info;
                }
            }
        }
        return true;
    }
    //找的是val的父节点
    public BTNode findDel(int val){
        if(root==null){
            return null;
        }
        if(val == root.val){
            return root;
        }
        BTNode p = root;
        while(p!=null){
            if(val < p.val){
                if(p.left != null && p.left.val == val){
                    return p;
                }else if(p.left == null){
                    return null;
                }else{
                    //存在但不相等
                    p = p.left;
                }
            }else{
                if(p.right !=null && p.right.val == val){
                    return p;
                }else if(p.right == null){
                    return null;
                }else{
                    p = p.right;
                }
            }
        }
        return null;
    }


  • 二叉排序树的不足
  • 假设我们需要建立一棵二叉排序树,但我们依次插入的元素是[1,2,3,4,5,6,7,8,9),那么我们实际插入的树其实以一颗只有右子树,没有左子树的树。那么其查找效率会退化为一个单链表。



相关文章
|
2月前
双链表的插入,删除以及遍历
双链表的插入,删除以及遍历
24 6
|
2月前
|
存储
单链表相关操作(插入,删除,查找)
单链表相关操作(插入,删除,查找)
27 4
|
9月前
|
关系型数据库 C++
红黑树的插入(C++实现)
红黑树的插入(C++实现)
23 0
|
2月前
|
NoSQL 容器 消息中间件
二叉搜索树查询/插入/求前驱/求后继/删除
二叉搜索树查询/插入/求前驱/求后继/删除
二叉搜索树查询/插入/求前驱/求后继/删除
|
2月前
|
存储
B-树的应用以及添加和删除操作
B-树的应用以及添加和删除操作
32 0
|
11月前
|
存储 C++
链表操作:插入、删除与遍历
(笔者画图不易呜呜)链表是一种基本的数据结构,它可以用来存储一系列的元素,并且支持灵活的插入、删除操作。在计算机科学中,链表常常用于构建更复杂的数据结构,如栈、队列以及图等。
235 0
|
12月前
|
存储 C语言
数据结构实验二 线性表顺序结构的删除、插入操作
数据结构实验二 线性表顺序结构的删除、插入操作
209 0
|
算法
单链表结点的插入与删除
单链表结点的插入与删除
87 0
|
算法
一天一个算法——>二叉搜索树的插入、查询、删除
一天一个算法——>二叉搜索树的插入、查询、删除
65 0
|
搜索推荐
查找-之二叉排序树(查找、插入、删除)
有序的线性表采用:折半/二分、插值、斐波那契查找相比顺序查找效率得到提高,但是在插入和删除时效率低(为维持数据的有序性) 在高效实现查找操作时,如何提高插入和删除的效率? 在一些应用场景:在查找时需要插入和删除
99 0
查找-之二叉排序树(查找、插入、删除)