day12二叉搜索树

day12二叉搜索树

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

概述

  • 树节点增加key属性,用来比较谁大谁小,key不可以重复
  • 对于任意一个树节点,它的key比左子树的key都大,同时也比右子树的key都小

二叉搜索树节点类

public class BSTTree {
    /**
     * 二叉搜索树节点类
     */
    static class BSTNode {
        //key属性
        int key;
        //value可以是任意内容
        Object value;
        //left是左节点
        BSTNode left;
        //right是右节点
        BSTNode right;
        
        public BSTNode(int key) {
            this.key = key;
        }

        public BSTNode(int key, Object value, BSTNode left, BSTNode right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }

        public BSTNode(int key, Object value) {
            this.key = key;
            this.value = value;
        }
    }
}

查找关键字时对应的值

使用递归
/**
     * 查找关键字对应的值
     * @param key
     * @return
     */
    public Object get(int key){
        return doGet(root,key);
    }

    /**
     * 创建一个方法使用递归去查找关键字对应的值
     * @param node
     * @param key
     * @return
     */
    private Object doGet(BSTNode node,int key){
        //没找到的情况
        if(node == null){
            return null;
        }
        //判断如果查找的key比当前的key小的话,去左边继续找
        if(key< node.key){
            return doGet(node.left,key);
        }
        //如果查找的key比当前的key大的话,去右边继续找
        else if(key > node.key){
            return doGet(node.right,key);
        }
        //否则找到的话就返回当前的值
        else{
            return node.value;
        }
    }
测试
public class Test {
    public static BSTTree createTree(){
        /**
         *                  4
         *                /   \
         *               2     6
         *              / \   / \
         *             1   3 5   7
         */
        BSTTree.BSTNode n1 = new BSTTree.BSTNode(1, "张无忌");
        BSTTree.BSTNode n3 = new BSTTree.BSTNode(3, "宋青书");
        BSTTree.BSTNode n2 = new BSTTree.BSTNode(2, "周芷若",n1,n3);

        BSTTree.BSTNode n5 = new BSTTree.BSTNode(5, "说不得");
        BSTTree.BSTNode n7 = new BSTTree.BSTNode(7, "引力");
        BSTTree.BSTNode n6 = new BSTTree.BSTNode(6, "赵敏",n5,n7);
        BSTTree.BSTNode root = new BSTTree.BSTNode(4, "小昭",n2,n6);

        BSTTree tree = new BSTTree();
        tree.root = root;
        return tree;
    }

    public static void main(String[] args) {
        BSTTree tree = createTree();
        Object o = tree.get(1);
        System.out.println(o);
    }


}

不使用递归
/**
     * 使用非递归的方式查找关键字对应的值
     * @pajian'zy
     * @return
     */
    public Object get1(int key){
        //让根节点赋值为node
        BSTNode node = this.root;
        //循环遍历,直到node不为空
        while (node != null){
            //判断如果查找的key比当前节点的key
            if(key < node.key){
                //将当前的node节点变为左节点
                node = node.left;
            }
            //判断如果查找的key比当前节点的key大的话
            else if(key > node.key){
                //将当前的node节点变为右节点
                node = node.right;
            }else{
                //否则返回node.value值
                return node.value;
            }
        }
        return null;
    }
测试
public class Test {
    public static BSTTree createTree(){
        /**
         *                  4
         *                /   \
         *               2     6
         *              / \   / \
         *             1   3 5   7
         */
        BSTTree.BSTNode n1 = new BSTTree.BSTNode(1, "张无忌");
        BSTTree.BSTNode n3 = new BSTTree.BSTNode(3, "宋青书");
        BSTTree.BSTNode n2 = new BSTTree.BSTNode(2, "周芷若",n1,n3);

        BSTTree.BSTNode n5 = new BSTTree.BSTNode(5, "说不得");
        BSTTree.BSTNode n7 = new BSTTree.BSTNode(7, "引力");
        BSTTree.BSTNode n6 = new BSTTree.BSTNode(6, "赵敏",n5,n7);
        BSTTree.BSTNode root = new BSTTree.BSTNode(4, "小昭",n2,n6);

        BSTTree tree = new BSTTree();
        tree.root = root;
        return tree;
    }

    public static void main(String[] args) {
        BSTTree tree = createTree();
        Object o = tree.get1(2);
        System.out.println(o);
    }
}

泛型key

public class BSTTree1<T extends Comparable<T> ,V> {
    /**
     * 二叉搜索树节点类
     */
    static class BSTNode<T,V> {
        T key;
        V value;
        BSTNode left;
        BSTNode right;

        public BSTNode(T key) {
            this.key = key;
        }

        public BSTNode(T key, V value, BSTNode<T,V> left, BSTNode<T,V> right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }

        public BSTNode(T key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    BSTNode<T,V> root;

    public Object get(T key){
        BSTNode<T,V> p = this.root;
        while ( p !=null){
            //key  p.key
            /**
             *    -1  key < p.key
             *    0   key == p.key
             *    1   key > p.key
             */
            int result = key.compareTo(p.key);
            if(result<0){
                p = p.left;
            }else if(result>0){
                p = p.right;
            }else{
                return p.value;
            }
        }
        return null;
    }
}


寻找最小值对应的关键字

递归
/**
     * 使用递归的方式查找最小关键字对应的值
     * @return
     */
    public Object min1(BSTNode node){
        //当传过来的节点为null值的时候返回null
        if(node == null){
            return null;
        }
        //判断如果当前节点的最左侧为null的话,说明已经找到最小值了,可以直接返回
       if(node.left == null){
           return node.value;
       }
        //否则的话,一直递归直到找到当前节点的左侧为null
      return min1(node.left);
    }
非递归
/**
     * 查找最小关键字对应值
     * @return
     */
    public Object min(){
        //curr代表着当前节点
        BSTNode curr = this.root;
        //判断如果curr为null的话此时的最小节点压根就不存在
        if(curr == null){
            return null;
        }
        //一直遍历到curr.left不为null
        while (curr.left != null){
           curr = curr.left;
        }
        //最终返回当前节点的value
        return curr.value;
    }

寻找最大值对应的关键字

递归
/**
     * 查找最大关键字对应的值
     * @return
     */
    public Object max(BSTNode node){
        if(node == null){
            return null;
        }
        if(node.right == null){
            return node.value;
        }
        return max(node.right);
    }
非递归
/**
     * 查找最大关键字对应的值
     * @return
     */
    public Object max1(){
        BSTNode curr = this.root;
       if(curr == null){
           return null;
       }
       while (curr.right != null){
           curr = curr.right;
       }
       return curr.value;
    }

存储关键字和对应值

/**
     * 存储关键字和对应值
    * @param key
     * @param value
     */
    public void put(int key,Object value){
        //1.key  有的话  更新操作
        BSTNode node = this.root;
        BSTNode parent = null;  //没有找到的时候的最后一个节点
        while (node != null){
            //更新parent节点
            parent = node;
            if(key < node.key){
                node = node.left;
            }else if(key > node.key){
                node = node.right;
            }else{
                //找到了,更新最新节点的值
                node.value = value;
                return;
            }
        }
        //parent   父节点
        //如果找到的父节点为空的话,此时添加的节点就应该是父节点
        if(parent == null){
            root = new BSTNode(key,value);
        }
        //2.key  没有的话  新增
        //new BSTNode(key,value);
        //判断新的key和父亲的key哪个值更大,如果父亲的大的话就给左边添加
        if(key < parent.key){
            parent.left = new BSTNode(key,value);
        }
        //如果右侧的key比父亲的key大的话,就给右面添加
        else if(key > parent.key){
            parent.right = new BSTNode(key,value);
        }
    }

前任和后任

后任

    /**
     * 寻找一个节点的最小值
     * @param node
     * @return
     */
    private Object min2(BSTNode node) {
        BSTNode curr = node;
        if(curr == null){
            return null;
        }
        while (curr.left != null){
            curr = curr.left;
        }
        return curr.value;
    }

    /**
     * 查找关键字的后任值
     * @param key
     * @return
     */
    public Object successon(int key){
        BSTNode p = root;
        BSTNode ancestorFromRight = null;//自左而来的祖先
        while (p != null){
            if(key < p.key){
                //这一行代码代表的就是找左边,所以可以确定是从右边来的
                ancestorFromRight = p;
                p = p.left;
            }else if(p.key < key){
                p= p.right;
            }else{
                break;
            }
        }
        //没找到节点
        if(p == null){
            return null;
        }
        /**
         *      情况1:节点有右子树,此时前任就是左子树的最小值
         *      情况2:节点没有右子树,若离它最近的,自右而来的祖先就是后任
         */
        //情况1
        if(p.right != null){
            return min2(p.left);
        }
        //情况2
        return ancestorFromRight != null ?ancestorFromRight.value:null;
    }
前任
 /**
     * 寻找任意一个节点的最大值
     * @param node
     * @return
     */
    private Object max2(BSTNode node){
        if(node == null){
            return null;
        }
        BSTNode p = node;
        while (p.right != null){
            p = p.right;
        }
        return p.value;
    }

    /**
     * 查找关键字的前任值
     * @param key
     * @return
     */
    public Object predecessor(int key){
        BSTNode p = root;
        BSTNode ancestorFromLeft = null;//自左而来的祖先
        while (p != null){
            if(key < p.key){
                p = p.left;
            }else if(p.key < key){
                //这一行代码代表的就是找右边,所以可以确定是从左边来的
                ancestorFromLeft = p;
                p= p.right;
            }else{
                break;
            }
        }
        //没找到节点
        if(p == null){
            return null;
        }
        /**
         *      情况1:节点有左子树,此时前任就是左子树的最大值
         *      情况2:节点没有左子树,若离它最近的,自左而来的祖先就是前任
         */
        //情况1
        if(p.left != null){
            return max(p.left);
        }
        //情况2
        return ancestorFromLeft != null ?ancestorFromLeft.value:null;
    }

删除

 /**
     * 根据关键字删除对应值
     * @param key
     * @return
     */
    public Object delete(int key){
        BSTNode p = root;
        BSTNode parent = null;//记录父节点
        while ( p!= null){
            if(key < p.key){
                parent = p;
                p = p.left;
            }else if(p.key < key){
                parent = p;
                p = p.right;
            }else{
                break;
            }
        }
        if(p == null){
            return null;
        }
        /**
         * 删除节点:    1.删除节点没有左孩子,将右孩子托孤给parent
         *             2.删除节点没有右孩子,将左孩子托孤给parent
         */
        //删除操作
        if(p.left == null){
            //情况1
            shift(parent,p,p.right);
        }else if(p.right == null){
            //情况2
            shift(parent,p,p.left);
        }else{
            //情况四
            //1.找到被删除节点的后继节点
            BSTNode s = p.right;
            BSTNode sParent = p;//后继父亲
            while (s.left != null){
                sParent = s;
                s = s.left;
            }
            //后继节点即为s
            //如何判断需不需要处理后事节点
            //如果后继节点的父亲就是删除的节点的话,就代表着不需要处理后事节点,否则就需要处理后事节点
            //2.处理后继的后事
            if(sParent != p){
                //删除和后继不相邻,处理后继的节点
                shift(sParent,s,s.right);//不可能有左孩子的
                s.right = p.right;
            }
            //3.后继取代被删除节点
            shift(parent,p,s);//此时的s就是后继节点,此时的p就是删除节点,parent就是删除节点的父节点
            s.left = p.left;
        }
        return p.value;
    }


 /**
     * 实现托孤方法
     *  parent被删除的节点
     *  deleted被删除的节点
     *  child被顶上去的节点
j    */
    private void shift(BSTNode parent,BSTNode deleted,BSTNode child){
        //判断如果当前节点的父节点是空的话,此时的根节点就应该变为child
        if(parent == null){
            root = child;
        }
        //判断如果删除的节点是父节点的左节点的话,那么父元素左节点就是子节点
        else if(deleted == parent.left){
            parent.left = child;
        }
        //判断如果删除的节点是父节点的右节点的话,那么父元素右节点就是子节点
        else{
            parent.right = child;
        }
    }

}
return p.value;
}

/**
* 实现托孤方法
* parent被删除的节点
* deleted被删除的节点
* child被顶上去的节点
j */
private void shift(BSTNode parent,BSTNode deleted,BSTNode child){
//判断如果当前节点的父节点是空的话,此时的根节点就应该变为child
if(parent == null){
root = child;
}
//判断如果删除的节点是父节点的左节点的话,那么父元素左节点就是子节点
else if(deleted == parent.left){
parent.left = child;
}
//判断如果删除的节点是父节点的右节点的话,那么父元素右节点就是子节点
else{
parent.right = child;
}
}


  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值