美文网首页算法与数据结构随笔-生活工作点滴
算法与数据结构系列之[二分搜索树-下]

算法与数据结构系列之[二分搜索树-下]

作者: 秦老厮 | 来源:发表于2019-07-10 09:40 被阅读1次

    上篇贴出了二分搜索树的C语言代码,这篇贴出二分搜索树的java实现代码。

    public class BinarySearchTree<E extends Comparable<E>> {  //一个泛型类型E需要实现一个接口的语法是使用extends关键字的
                                                                // 实现了Comparable这个借口的类视作可比较的类
                                                              //之后重写compareTo方法就可在内部自定义比较方式
        private class Node{
            public E e;  //节点的值
            public Node left,right;  //二分搜索树的左节点和右节点
            public Node(E e){
                this.e = e;
                this.left = null;
                this.right = null;
            }
        }
    
        private Node root;  //根节点
        private int size;  //节点的个数
    
        public BinarySearchTree(){
            this.root = null;
            this.size = 0;
        }
    
        //获取节点个数
        public int getSize(){
            return size;
        }
    
        //判断节点是否为空
        public boolean isEmpty(){
            return size == 0;
        }
    
        //向二分搜索树添加新的元素e
        public void add(E e){
           root = add(root,e);
    
    
        }
    
        //向以node为根节点的二分搜索树新的元素e,采用递归算法
        //返回插入新节点后二分搜索树的根
        private Node add(Node node,E e){
    
           if(node == null){
               size++;
               return new Node(e);
           }
    
           if(e.compareTo(node.e) < 0)    //由于e不是基础类型,不能直接用<或>比较,而E是满足Comparable接口的,所以使用compareTo方法比较
               node.left = add(node.left,e);
           else if(e.compareTo(node.e) > 0)
               node.right = add(node.right,e);
           return node;
        }
    
        //查看二分搜索树中是否包含元素e
        public boolean contains(E e){
            return contains(root,e);
        }
    
        //查看以node为根的二分搜索树中是否包含元素e
        private boolean contains(Node node,E e){
            if(node == null)
                return false;
            if(e.compareTo(node.e) == 0)
                return true;
            else if(e.compareTo(node.e) < 0)
                return contains(node.left,e);
            else
                return contains(node.right,e);
        }
    
        //二分搜索树的前序遍历
        public void preOrder(){
            preOrder(root);
        }
    
        //前序遍历以node为根的二分搜索树
        private void preOrder(Node node){
            if(node == null)
                return;
            System.out.print(node.e);
            preOrder(node.left);
            preOrder(node.right);
        }
    
        //二分搜索树的中序遍历
        public void inOrder(){
            inOrder(root);
        }
    
        private void inOrder(Node node){
            if(node == null)
                return;
            inOrder(node.left);
            System.out.print(node.e);
            inOrder(node.right);
        }
    
        //二分搜索树的后序遍历
        public void postOrder(){
            postOrder(root);
        }
    
        private void postOrder(Node node){
            if(node == null)
                return;
            postOrder(node.left);
            postOrder(node.right);
            System.out.print(node.e);
        }
    
        //二分搜索树的前序遍历,采用非递归方法
        public void preOrderNR(){
            Stack<Node> stack = new ArrayStack<>();
            stack.push(root);
            while (!stack.isEmpty()){
                Node cur = stack.pop();
                System.out.print(cur.e);
                if(cur.right != null)
                    stack.push(cur.right);
                if(cur.left != null)
                    stack.push(cur.left);
            }
        }
    
        //二分搜索树的层序遍历,广度优先,二分搜索树的前、中、后序遍历都是深度优先
        public void levelOrder(){
            Queue<Node> queue = new LinkedList<>();
            queue.add(root);
            while (!queue.isEmpty()){
                Node cur = queue.remove();
                System.out.print(cur.e);
                if(cur.left != null)
                    queue.add(cur.left);
                if(cur.right != null)
                    queue.add(cur.right);
            }
        }
    
        //寻找二分搜索树的最小元素
        public E minimum(){
            if(size == 0)
                throw new IllegalArgumentException("这是一棵空树");
            return minimum(root).e;
        }
    
        private Node minimum(Node node){
            if(node.left == null)
                return node;
            return minimum(node.left);
        }
    
        //寻找二分搜索树的最大元素
        public E maximum(){
            if(size == 0)
                throw new IllegalArgumentException("这是一棵空树");
            return maximum(root).e;
        }
    
        private Node maximum(Node node){
            if(node.right == null)
                return node;
            return maximum(node.right);
        }
    
        //删除二分搜索树中最小值所在的节点,并将最小值返回
        public E removeMin(){
            E ret = minimum();
            root = removeMin(root);
            return ret;
        }
    
        //删除以node为根的二分搜索树的最小节点
        //返回删除节点后新的二分搜索树的根(有可能二分搜索树只有根节点和它的右子节点,此时删除了根节点后,需要返回新的节点作为根节点)
        private Node removeMin(Node node){
            if(node.left == null){
                Node rightNode = node.right;
                node.right = null;
                size--;
                return rightNode;
            }
    
            node.left = removeMin(node.left);
            return node;
        }
    
        //删除二分搜索树中最大值所在的节点,并将最大值返回
        public E removeMax(){
            E ret = maximum();
            root = removeMax(root);
            return ret;
        }
    
        //删除以node为根的二分搜索树的最大节点
        //返回删除节点后新的二分搜索树的根
        private Node removeMax(Node node){
            if(node.right == null){
                Node leftNode = node.left;
                node.left = null;
                size--;
                return leftNode;
            }
    
            node.right = removeMax(node.right);
            return node;
        }
    
        //从二分搜索树中删除元素为e的节点
        public void remove(E e){
            root = remove(root,e);
        }
    
        //使用递归算法删除以node为根的二分搜索树的元素为e的节点
        //返回删除节点后二分搜索树的根
        private Node remove(Node node,E e){
            if(node == null)
                return null;
            if(e.compareTo(node.e)< 0){
                node.left = remove(node.left,e);
                return node;
            }
            else if(e.compareTo(node.e) >0){
                node.right = remove(node.right,e);
                return node;
            }
            else {  //e == node.e
                //待删除节点的左子树为空,右子树不为空
                if(node.left == null){
                    Node rightNode = node.right;
                    node.right = null;
                    size--;
                    return rightNode;
                }
                //待删除节点的右子树为空,左子树不为空
                if(node.right == null){
                    Node leftNode = node.left;
                    node.left = null;
                    size--;
                    return leftNode;
                }
                //待删除节点的左右子树都不为空
                //找到比待删除节点大的最小的节点,也就是待删除节点右子树的最小节点
                //用找到的最小节点代替待删除节点的位置
                Node successor = minimum(node.right);  //successor  待删除节点的后继,也就是待删除节点右子树的最小节点
                successor.right = removeMin(node.right);
                successor.left = node.left;
                node.left = node.right = null;
                return successor;
            }
        }
    
        public static void main(String[] args) {
            BinarySearchTree<Integer> bst = new BinarySearchTree<>();
            int[] nums = {5,3,7,8,6,4,2};
            for (int num : nums) {
                bst.add(num);
            }
            //二分搜索树的四种遍历
            bst.preOrder();
            System.out.println();
            bst.inOrder();
            System.out.println();
            bst.postOrder();
            System.out.println();
            bst.preOrderNR();
            System.out.println();
            bst.levelOrder();
            System.out.println();
            System.out.println("--------------------------------------");
            //删除最小节点
            bst.removeMin();
            bst.preOrder();
            System.out.println();
            //删除最大节点
            bst.removeMax();
            bst.preOrder();
            System.out.println();
            //删除指定的任意节点
            bst.remove(5);
            bst.preOrder();
        }
    }
    

    相关文章

      网友评论

        本文标题:算法与数据结构系列之[二分搜索树-下]

        本文链接:https://www.haomeiwen.com/subject/zqkckctx.html