BST树(java实现)

BST树二叉搜索树
左子树比根节点小,右子树比根节点大

BST树节点
public class BSTNode {
    int data;
    BSTNode left;
    BSTNode right;

    public BSTNode(int data, BSTNode left, BSTNode right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }
}

BST树常见操作:



public class BinarySearchTree {

    //BST树的根节点的引用
    public BSTNode root;

    public BinarySearchTree() {
        this.root = null;
    }

    /**
     * 非递归实现BST树的插入操作
     * @param val
     */
    public void insert_non(int val){

        //1.考虑根节点的特殊情况
        if(root == null){
            root = new BSTNode(val, null, null);
            return;
        }

        //2.寻找val值需要插入的地方
        BSTNode parent = null;
        BSTNode cur = root;
        while(cur != null){
            if(val < cur.data){
                parent = cur;
                cur = cur.left;
            } else if(val > cur.data){
                parent = cur;
                cur = cur.right;
            } else {
                return;
            }
        }

        //3.把val值生成新节点插入到BST树当中
        if(val < parent.data){
            parent.left = new BSTNode(val, null, null);
        } else {
            parent.right = new BSTNode(val, null, null);
        }
    }

    /**
     * 递归实现BST树的插入操作
     * @param val
     */
    public void insert(int val){
        root = insert(root, val);
    }

    /**
     * 从root节点开始寻找位置,插入val
     * @param root
     * @param val
     * @return
     */
    private BSTNode insert(BSTNode root, int val) {
        if(root == null){
            return new BSTNode(val, null, null);
        }
        if(val < root.data){
            root.left = insert(root.left, val);
        } else if(val > root.data){
            root.right = insert(root.right, val);
        }
        return root;
    }

    /**
     * 非递归实现BST的删除操作
     * 1.有两个孩子  用前驱或者后继节点代替一下
     * 2.有一个孩子
     * 3.叶子节点
     * @param val
     */
    public void remove_non(int val){
        //1.找到值为val的节点
        BSTNode parent = null;
        BSTNode cur = root;
        while(cur != null){
            if(val < cur.data){
                parent = cur;
                cur = cur.left;
            } else if(val > cur.data){
                parent = cur;
                cur = cur.right;
            } else {
                break;
            }
        }
        //要删除的结点不存在
        if(cur == null){
            return;
        }

        //2.处理有两个孩子的节点
        if(cur.left != null && cur.right != null){
            parent = cur;

            //用前驱节点来代替(左孩子的最后一个右子树结点)
            /*BSTNode p = cur.left;
            while(p.right != null){
                parent = p;
                p = p.right;
            }*/

            //用后继节点来代替 (右孩子的最后一个左子树结点)
            BSTNode p = cur.right;
            while(p.left != null){
                parent = p;
                p = p.left;
            }

            cur.data = p.data;
            cur = p;
        }

        //3.删除cur引用的节点   处理2,3的情况
        BSTNode child = cur.left;
        if(child == null){
            child = cur.right;
        }

        if(parent==null){     //删除根结点    根节点只有一个孩子
            root=child;
        } else if(cur.data < parent.data){  // cur在parent左孩子上
            parent.left = child;
        } else {
            parent.right = child;
        }
    }

    /**
     * 用递归删除BST树中值为val的节点
     * @param val
     */
    public void remove(int val){
        root = remove(root, val);
    }

    /**
     * 递归删除值为val的节点,删除以后,把根节点返回回去
     * @param root
     * @param val
     * @return
     */
    private BSTNode remove(BSTNode root, int val) {
        if(root == null){
            return null;
        }
        if(val < root.data){
            root.left = remove(root.left, val);
        } else if(val > root.data){
            root.right = remove(root.right, val);
        } else {
            //表示找到值为val的节点了
            if(root.left != null && root.right != null){
                //后继节点替换
                BSTNode p = root.right;
                while(p.left != null){
                    p = p.left;
                }
                root.data = p.data;
                root.right = remove(root.right, p.data);
            } else {
                //有一个孩子或者叶子节点
                if(root.left != null){
                    return root.left;
                }

                if(root.right != null) {
                    return root.right;
                }

                return null;
            }
        }
        return root;
    }

    /**
     * BST树的搜索,找值为val的节点是否存在
     * @param val
     * @return
     */
    public boolean query1(BSTNode root,int val){
        boolean res=false;
        if(root==null) {
            return false;
        }else if(root.data==val){
            return true;
        }else{
            res=query1(root.left,val);
            if(res==false){
                res=query1(root.right,val);
            }
            return res;
        }
    }

    /**
     * BST树的搜索,找值为val的节点是否存在  返回结点
     * @param val
     * @return
     */
    public BSTNode query(int val){
        return query(root, val);
    }
    /**
     * 递归搜索值为val的节点
     * @param root
     * @param val
     * @return
     */
    private BSTNode query(BSTNode root, int val) {
        if(root == null){
            return null;
        }
        if(val < root.data){
            return query(root.left, val);
        } else if(val > root.data){
            return query(root.right, val);
        } else{
            return root;
        }
    }

    /**
     * BST的前序遍历递归  VLR
     */
    public void preOrder(BSTNode root){
        if(root==null) return;
        System.out.print(root.data +" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    /**
     * 非递归前序遍历(栈来实现) 根节点入栈(从根结点开始的左子树的左孩子一直入栈直到NULL ),且在入栈之前打印结点的data,
     *                            出栈,root指向栈顶元素(当前结点)的右孩子  右孩子不为null 时  打印  并入栈 ;右孩子为NULL 继续出栈下一个元素;
     *
     * @param root
     */

    public void NicePreOrder(BSTNode root){
        if(root==null){
            return;
        }
        Stack<BSTNode> st=new Stack<BSTNode>();
        while(!st.isEmpty() || root!=null) {
            while (root != null) {
                System.out.print(root.data + " ");
                st.push(root);
                root = root.left;
            }
            if (!st.isEmpty()) {
                root = st.peek();
                st.pop();
                root = root.right;
            }
        }
    }


    /**
     * BST的中序遍历递归     LVR
     */
    public void inOrder(BSTNode root){
        if(root==null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.data +" ");
        inOrder(root.right);
    }

    /**
     *  非递归中序遍历
     *  从根节点开始到左孩子的left一直入栈
     *
     *  出栈,并打印 ,如果当前出栈元素的右孩子不为NULL(以及右孩子的左子树不为NULL)就全部入栈,如果为null  继续出栈下一个元素;
     * @param root
     */


    public void NiceInOder(BSTNode root){
        if(root==null){
            return;
        }
        Stack<BSTNode> st=new Stack<BSTNode>();
        while(!st.isEmpty() || root!=null) {
            while (root != null) {
                st.push(root);
                root = root.left;
            }
            root = st.peek();
            st.pop();
            System.out.print(root.data + " ");
            root = root.right;    //右孩子以及右孩子的左子树都入栈;
        }
    }


    /**
     * BST树的后序遍历   LRV   对每课树都是LRV
     */
    public void lastOrder(BSTNode root){
        if(root==null){
            return;
        }
        lastOrder(root.left);
        lastOrder(root.right);
        System.out.print(root.data +" ");
    }

    /**
     * 非递归后序
     *
     * 从根节点开始往left一直入栈
     * 出栈之前先判断当前栈顶元素的右孩子以及右孩子的左子树是否为NULL  不为null时先入栈
     *   为NULL时,就出栈并 打印栈顶元素
     * @param root
     *
     */
     //LRV   出栈之前先把右孩子以及右孩子的左子树都入栈
    public void NiceLastOrder(BSTNode root){
        if(root==null){
            return;
        }
        Stack<BSTNode> st=new Stack<BSTNode>();
        BSTNode tag=null;
        while (!st.isEmpty() || root!=null){
            while(root!=null){
                st.push(root);
                root=root.left;
            }
            root=st.peek();
            st.pop();
            if(root.right==null || root.right==tag){  //找栈顶值的右孩子
                System.out.print(root.data+" ");
                tag=root;
                root=null;
            }else{              //有右孩子
                st.push(root);
                root=root.right;
            }
        }
    }


    /**
     * 层序遍历    出队打印后把左右孩子都入队
     */
    public void levelOrder(BSTNode root){
        if(root==null){
            return;
        }
        Queue<BSTNode> qu=new LinkedList<BSTNode>();
        qu.add(root);
        while (!qu.isEmpty()){
            root=qu.peek();   //从对头获取元素
            qu.poll();        //从队中移出
            System.out.print(root.data+" ");
            if(root.left!=null){
                qu.add(root.left);
            }
            if(root.right!=null){
                qu.add(root.right);
            }
        }
    }

    /**
     *
     * @param root
     */
    public void LeveOrder(BSTNode root){
        int height=height(root);
        for(int i=0;i<=height;i++){
            leve(root,i);
        }
        System.out.println();
    }

    private void leve(BSTNode root, int i) {
        if(root==null){     //BST不一定是一颗完全树
            return;
        }
        if(i==1) {
            System.out.print(root.data +" ");
        }
        leve(root.left,i-1);
        leve(root.right,i-1);

    }


    /**
     * 递归实现求BST树的高度/层数
     * @return
     */
    public int height(BSTNode root){
        if(root==null){
            return 0;
        }
        return height(root.left)>height(root.right)?height(root.left)+1:height(root.right)+1;
    }

    /**
     * 递归实现求BST树节点的个数
     * @return
     */
    public int number(BSTNode root){
        if(root==null){
            return 0;
        }
        return number(root.right)+number(root.left)+1;
    }

    /**
     * 求二叉树满足某一个区间[begin, end]的所有节点的值,放入list当中
     */
    public List<Integer> findAreaValue(int begin, int end){
        List<Integer> list=new ArrayList<Integer>();
        findValue(root,list,begin,end);
        return list;
    }

    private void findValue(BSTNode root, List<Integer> list, int begin, int end) {
        if(root!=null){
            findValue(root.left,list,begin,end);
            if(root.data>begin && root.data<end){
                list.add(root.data);
            }else if(root.data>end){
                return;
            }
            findValue(root.right,list,begin,end);
        }
    }

    /**
     * 求BST的镜像   交换每一颗子树的左右孩子
     */
    public void mirror(BSTNode root){
        if(root == null){
            return;
        }
        Stack<BSTNode> stack = new Stack<BSTNode>();
        stack.push(root);
        while(!stack.isEmpty()){
            BSTNode node = stack.pop();
            if(node.left != null||node.right != null){
                BSTNode temp = node.left;
                node.left = node.right;
                node.right = temp;
            }
            if(node.left!=null){
                stack.push(node.left);
            }
            if(node.right!=null){
                stack.push(node.right);
            }
        }
    }

    /**
     * 递归求镜像
     * @param root
     */
    public void mirror1(BSTNode root){
        if(root==null){
            return;
        }
        BSTNode temp =root.left;
        root.left = root.right;
        root.right = temp;
        mirror1(root.left);
        mirror1(root.right);
    }


    /**
     * 判断形参bst树,是不是当前BST树(this)的一颗子树结构
     * @param bst
     * @return
     */
    public boolean isChildTree(BinarySearchTree bst){
        boolean res=false;
        //当Tree1和Tree2都不为null的时候才可以比较
        if(this!=null && bst!=null) {
            //如果找到了对应的Tree2的根节点的点
            if (this.root.data == bst.root.data) {
                res=HaveTree(this.root,bst.root);
                //如果未找到,则以根节点的左孩子为起点,去判断是否包含Tree2
                if(!res){
                    res=HaveTree(this.root.left,bst.root);
                }
                //如果未找到,则以根节点的右孩子为起点,去判断是否包含Tree2
                if(!res){
                    res=HaveTree(this.root.right,bst.root);
                }
            }
        }
        return res;
    }

    private boolean HaveTree(BSTNode root1, BSTNode root2) {
        //root2遍历完了  全部匹配
        if(root2==null){
            return true;
        }else if(root1==null){       //root1先遍历完了   root2中存在在root1没有的结点;
            return false;
        }
        if(root1==null && root2==null){    //两棵树的结点一直相等,直到结点遍历完了
            return true;
        }
        if(root1.data!=root2.data){
            return false;
        }
        //如果根节点对应的上,那么就分别去子节点里面匹配
        return  HaveTree(root1.left, root2.left)&& HaveTree(root1.right, root2.right);
    }


    /**
     * 从root节点开始,求val1和val2的最近公共祖先节点,并返回该祖先节点的值val   LCA
     * @param val1
     * @param val2
     * @return
     */
    public int getLCA1(int val1, int val2){
        BSTNode node1 = query(val1);
        BSTNode node2 = query(val2);
        return getLCA(root, node1, node2);
    }

    /**
     *
     * @param root
     * @param node1
     * @param node2
     * @return
     */
    private int getLCA(BSTNode root, BSTNode node1, BSTNode node2) {

        if(node1.data < root.data && node2.data < root.data){
            return getLCA(root.left, node1, node2);
        } else if(node1.data > root.data && node2.data > root.data){
            return getLCA(root.right, node1, node2);
        } else {
            return root.data;
        }
    }

    /**
     * 从root节点开始,求val1和val2的最近公共祖先节点,并返回该祖先节点的值val   LCA
     * @param val1
     * @param val2
     * @return
     */
    public int getLCA(int val1, int val2){
        if(root==null){
            return -1;
        }
        while(root!=null){
            if(root.data>val1 && root.data>val2){
                root=root.left;
            }else if(root.data<val1 && root.data<val2){
                root=root.right;
                }else {
                return root.data;
            }
        }
        return -1;
    }

    /**
     * 寻找中序遍历第K个节点
     * @param k
     * @return
     */
    public int getInOrderNoK(BSTNode root,int k){
        int count=0;
        Stack<BSTNode> st=new Stack<BSTNode>();
        if(count>k || root==null){
            return -1;
        }
        while(!st.isEmpty()|| root!=null) {
            while (root != null) {
                st.push(root);
                root = root.left;
            }
            root = st.peek();
            count++;
            if (count == k) {
                return root.data;
            }
            st.pop();
            root = root.right;
        }
        return -1;
    }
  }

猜你喜欢

转载自blog.csdn.net/xd_fybdw/article/details/80959168