数据结构与算法 二叉树与二叉搜索树

树的基本概念

  • 节点、根节点、父节点、子节点、兄弟节点
  • 一棵树可以没有任何节点,成为空树
  • 一棵树可以只有一个节点,也就是只有根节点
  • 子树、左子树、右子树
  • 节点的度 :子树的个数
  • 树的度:所有节点度中的最大值
  • 叶子节点:节点度为0 的
  • 层数:根节点在第一层,根节点的子节点在第二层(有些教程从第0层开始计算)
  • 节点的深度:从根节点到当前节点的唯一路径上的节点总和(从上往下看)
  • 节点的高度:从当前节点到最远的叶子节点的路径上的节点总数 (从下往上看)
  • 树的深度:所有节点深度中的最大值
  • 树的高度:所有节点高度中的最大值
  • 树的高度 等于树的深度

                       

有序树:

树中任意节点的子节点之间有顺序关系

无序树:

树中任意节点的子节点之间没有顺序关系

森林:

由m棵不相交的树组成的集合

二叉树(Binary Tree)

  • 每个节点的度最大为2(最多拥有2棵子树)
  • 左子树和右子树是有顺序的
  • 即使某个节点只有一棵树,也要区分左右子树
  • 非空二叉树的第i层,最多有 个节点(i>=1)
  • 在高度为h的二叉树上最多有个节点(h>=1)
  • 对于任何一棵非空二叉树,如果叶子节点个数为n0,度为2节点个数为n2,则有 n0 = n2 +1

     假设 度为1 的节点个数为n1,那么二叉树的节点总数 n = n0 + n1 +n2

     二叉树的边数  T = N1+2*N2 = N-1 = N0+ N1 +N2 -1 推导出 n0 = n2 +1

                                    

真二叉树(Proper Binary Tree)

所有节点的度都要么为0,要么为2

                                                                 

满二叉树(Full Binary Tree)

  • 所有节点的度都要么为0,要么为2。且所有的叶子节点都在最后一层
  • 在同样高度的二叉树中,满二叉树的叶子节点数量最多、总节点数量最多
  • 满二叉树一定是真二叉树,真二叉树不一定是满二叉树

 完全二叉树(Complete Binary Tree)

  • 叶子节点只会出现最后2层,且最后1层的叶子节点都靠左对齐
  • 完全二叉树从根节点至倒数第2层是一棵满二叉树
  • 满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
  • 度为1的节点只有左子树
  • 度为1的节点要么是1个,要么是0个
  • 同样节点数量的二叉树,完全二叉树的高度最小
  • 假设完全二叉树的高度为h(h >=1),那么至少 个节点 最多 个节点
  • 总节点数量 为n 

 

一棵有n个节点的完全二叉树(n>0),从上倒下、从左到右对节点从1开始编号,对任意第i个节点:

  • 如果i=1,它是根节点
  • 如果i>1,它的父节点变化为 floor(i/2)
  • 如果2i<n,它的左子节点编号为2i
  • 如果2i>n,它无左子节点
  • 如果2i+1<=n,它的右子节点编号为2i+1
  • 如果2i+1>n,它无右子节点

                                                        

 一棵有n个节点的完全二叉树(n>0),从上倒下、从左到右对节点从9开始编号,对任意第i个节点:

  • 如果i=0,它是根节点
  • 如果i>0,它的父节点变化为 floor(i-1/2)
  • 如果2i+1<n-1,它的左子节点编号为2i+1
  • 如果2i+1>n-1,它无左子节点
  • 如果2i+2<=n-1,它的右子节点编号为2i+2

                                                         

Full Binary Tree:完满二叉树

  • 所有非叶子节点的度都为2
  • 就是国内说的“真二叉树”

                                

Perfect Binary Tree:完美二叉树

  • 所有的非叶子结点的度都为2,且所有的叶子节点都在最后一层
  • 就是国内的“满二叉树“ 

                                

Complete Binary Tree:完全二叉树

  • 和国内的完全二叉树一样 

                                 

在n个动态的整数中搜索某个整数?查看其是否存在

  • 假设使用动态数组存放元素,从第0个位置开始遍历元素,平均时间复杂度:O(N)

  • 如果维护一个有序动态数组,使用二分搜素,最坏时间复杂度:O(logn),但是添加、删除的平均时间复杂度是O(N)

针对这种需求,有没有更好的方案?

  • 使用二叉搜索树,添加、删除、搜索的最坏四件复杂度均可优化至:O(logn)

二叉搜索树

介绍

二叉搜索树是二叉树的一种,是应用非常广泛的一种二叉树,简称BST

  • 又被成为:二叉查找树,二叉排序树
  • 任意一个节点的值都大于其左子树的所有节点的值
  • 任意一个节点的值都小于其右子树所有节点的值
  • 它的左右子树也是一棵二叉搜索树
  • 二叉搜索树可以大大提高搜索数据的效率
  • 二叉搜索树存储的元素必须具备可比较性

     比如int、double等

    如果是自定义类型,需要指定比较方式、不允许为null

                                                             

添加元素

  • 找到父节点parent
  • 创建新节点node
  • parent.left = node 或者 parent.right = node
 // 添加元素
    public void add(E element) {
        elementNotNullCheck(element);
        if (root == null) {
            // 添加第一个节点
            root = new Node<>(element, null);
            size++;
            return;
        }
        // 添加不是第一个节点
        // 找到父节点
        Node<E> parent = null;
        Node<E> node = root;
        int cmp = 0;
        while (node != null) {
            cmp = compare(element, node.element);
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) { // 新加的元素比父节点小
                node = node.left;
            } else { // 相等 将对象覆盖
                node.element = element;
                return;
            }
        }

        // 看看插入到副节点的哪个位置
        Node<E> newNode = new Node<>(element, parent);
        if (cmp > 0) {
            parent.right = newNode;
        } else {
            parent.left = newNode;
        }
        size++;
    }

删除元素-叶子节点

  • 直接删除

        node == node.parent.left ; node.parent.left == null

        node == node.parent.right; node.parent.right == null

        node.parent == null; root ==null

                                               

删除元素-度为1的节点

  • 用子节点代替原节点的位置 

        child是node.left 或者 child 是node.right,用child替代node位置 。

        如果node是左子节点  child.parent = node.parent; node.parent.left = child;

        如果node是右子节点  child.parent = node.parent; node.parent.right = child;

        如果node 是根节点  root = child ;  child.parent = null;

     

                       

删除节点-度为2的节点

 举例:先删除5、在删除4

  • 先用前驱或者后继节点的值覆盖原节点的值
  • 然后删除响应的前驱节点或者后继节点

 如果一个节点的度为2,那么 它的前驱、后继节点的度只可能是1 和 0

       

  // 删除元素
    public void remove(E elemet) {
        remove(node(elemet));
    }

    // 删除元素
    public void remove(Node<E> node) {

        if (node == null) return;
        size--;

        // 度为2的节点
        if (node.hasTwoChildren()) {
            // 找到后继节点
            Node<E> s = successor(node);
            // 用后继节点的值 覆盖度为2的节点的值
            node.element = s.element;
            // 删除后继节点
            node = s;
        }

        // 删除node节点(node的度必然是1 或者 0)
        Node<E> repalcement = node.left != null ? node.left : node.right;

        if (repalcement != null) { // node的度是1
            // 更改
            repalcement.parent = node.parent;
            if (node.parent == null) {// node的度是1 并且是根节点
                root = repalcement;
            } else if (node == node.parent.left) {
                node.parent.left = repalcement;
            } else if (node == node.parent.right) {
                node.parent.right = repalcement;
            }
        } else if (node.parent == null) {  // node的度是0 叶子节点 并且是根节点
            root = null;
        } else { // node的度是0 叶子节点 但不是根结点
            if (node == node.parent.right) {
                node.parent.right = null;
            } else {
                node.parent.left = null;
            }
        }
    }

    private Node<E> node(E element) {
        Node<E> node = root;
        while (node != null) {
            int cmp = compare(element, node.element);
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) { // 新加的元素比父节点小
                node = node.left;
            } else { // 相等 将对象覆盖
                return node;
            }
        }
        return null;
    }

 前序遍历

  • 根节点、前序遍历左子树、前序遍历右子树
  • 7、4、2、1、3、5、9、8、11、10、12

 

 

 

                                  

    /**
     * 前序遍历
     */
    public void preorderTraversal() {
        preorderTraversal(root);
    }

    public void preorderTraversal(Node<E> node) {
        if (node == null) return;
        System.out.println(node.element);
        preorderTraversal(node.left);
        preorderTraversal(node.right);
    }

 中序遍历

  • 中序遍历左子树、根节点、中旬遍历右子树
  • 1、2、3、4、5、7、8、9、10、11、12

                                            

    /**
     * 中旬遍历
     */
    public void inorderTraversal() {
        inorderTraversal(root);
    }

    public void inorderTraversal(Node<E> node) {
        if (node == null) return;
        inorderTraversal(node.left);
        System.out.println("BinarySearchTree.inorderTraversal:" + node.element);
        inorderTraversal(node.right);

    }

后序遍历

  • 后序遍历左子树、后序遍历右子树、根节点
  • 1、3、2、5、4、8、10、12、11、9、7

 

                                       

  /**
     * 后续遍历
     */
    public void postorderTraversal() {
        postorderTraversal(root);
    }

    public void postorderTraversal(Node<E> node) {
        if (node == null) return;
        postorderTraversal(node.left);
        postorderTraversal(node.right);
        System.out.println("BinarySearchTree.inorderTraversal:" + node.element);
    }

层序遍历

  • 从上到下、从左到右依次访问每个节点

  • 7、4、9、2、5、8、11、1、3、10、12

  • 实现思路:使用队列 

     1、将根节点入队

     2、循环执行以下操作,直到队列为空

  •          将队头节点A出队,进行访问
  •          将A的左子节点入队
  •          将A的右子节点入队

                                                         

  /**
     * 层序遍历
     */
    public void leverOrderTraversal() {
        if (root == null) return;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            System.out.println("BinarySearchTree.leverOrderTraversal:" + node.element);
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }

 遍历的应用

  • 前序遍历:树状结构展示
  • 中旬遍历:二叉搜索树的中旬遍历按升序或者降序处理节点
  • 后序遍历:使用于一些先子后父的操作
  • 层序遍历:计算二叉树的高度、判断一棵树是否为完全二叉树

计算二叉树的高度

  • 递归方式:计算某个节点的高度,其实就是计算它的左子树右子树最大高度+1
 public Integer hight() {
        return hight(root);
    }

    public int hight(Node<E> node) {
        if (node == null) return 0;
        return 1 + Math.max(hight(node.left), hight(node.right));
    }
  • 非递归方式:使用层序遍历,通过每层的数据出队完成即为高度+1
  public Integer hight2() {
        if (root == null) return 0;
        Queue<Node<E>> queue = new LinkedList<>();
        int queueSize = 1;
        int hight = 0;
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            queueSize--;
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
            if (queueSize == 0) {
                queueSize = queue.size();
                hight++;
            }
        }
        return hight;
    }

判断一棵树是否为完全二叉树

  • 如果树为空,返回false

  • 如果树不为空,开始层序遍历二叉树

  • 如果node.left !=null && node.right!=null将node.left、node.right 按顺序入队列

  • 如果node.left == null && node.right!=null 返回false

  • 如果node.left!=null && node.right==null 或者node.left==null && node.right == null 

        那么后面的遍历节点应该都为叶子节点,才是完全二叉树,否则返回false 

public boolean isComplete() {
        if (root == null) return false;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        boolean leaf = false;
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();

            if (leaf && !node.isLeaf()) return false;

            if (node.hasTwoChildren()) {
                queue.offer(node.left);
                queue.offer(node.right);
            } else if (node.left == null && node.right != null) {
                return false;
            } else {
                // 判断是否都是叶子节点
                leaf = true;
                if (node.left != null) {
                    queue.offer(node);
                }
            }
        }
        return true;
    }

    public boolean isCompleteOther() {
        if (root == null) return false;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        boolean leaf = false;
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            if (leaf && !node.isLeaf()) return false;
            if (node.left != null) {
                queue.offer(node.left);
            } else if (node.right != null) {
                //node.left == null && node.right!=null,
                return false;
            }
            if (node.right != null) {
                queue.offer(node.right);
            } else {
                //node.left !=null && node.right==null 或者 node.left ==null && node.right == null
                leaf = true;
            }
        }
        return true;
    }

翻转二叉树

public class Rollover {

    /**
     * 翻转二叉树  前序遍历
     * @param root
     * @return
     */
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;

        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        invertTree(root.left);
        invertTree(root.right);

        return root;
    }

    /**
     * 翻转二叉树  后序遍历
     * @param root
     * @return
     */
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;

        invertTree(root.left);
        invertTree(root.right);

        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        return root;
    }

    /**
     * 翻转二叉树  中序遍历
     * @param root
     * @return
     */
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;

        invertTree(root.left);
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        invertTree(root.left);
        return root;
    }

    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }
}

根据遍历结果重构二叉树

  • 前序遍历+中序遍历
  • 后序遍历+中序遍历

                         前序遍历:4 2 1 3 6 5

                         中序遍历:1 2 3 4 5 6                                           

                          

前驱节点 

  • 中序遍历时的前一个节点

             如果是二叉搜索树,前驱节点就是前一个比它小的节点

  •      node.left !=null  举例 :6、13、8  ,predecessor = node.left.right.right.right....,终止条件:right 为null
  •      node.left == null && node.parent !=null 举例:7、11、9、1,predecessor = node.parent.parent....,终止条件:node 在parent的右子树中
  •     node.left == null && node.parent ==null   那就是没有前驱节点

                               

 /**
     * 获取前驱节点
     * @param node
     * @return
     */
    public Node<E> predecessor(Node<E> node) {
        if (node == null) return null;
        Node<E> p = node.left;
        // 前驱节点在左子树当中 left.right.right.right
        if (p != null) {
            while (p.right != null) {
                p = p.right;
            }
            return p;
        }
        // 从父节点、祖父节点中国呢寻找前驱节点
        Node<E> parent = node.parent;
        while (parent != null && node == node.parent.left) {
            node = node.parent;
        }

        return node.parent;
    }

 

后继节点

  • 后继节点:中序遍历时的后一个节点

          如果时二叉搜索树,后继节点就是后一个比它大的节点

  • node.right!=null 举例 1、8、4 suceessor = node.right.left.left.left.... 终止条件:left 为null
  • node.right == null && node.parent !=null 举例 7、6、3、11 suceessor = node.parent.parent.parent.... 终止条件: node在parent的左子树中
  • node.right == null && node.parent ==null 那就没有后继节点 
 /**
     * 获取后继节点
     * @param node
     * @return
     */
    public Node<E> successor(Node<E> node) {
        if (node == null) return null;
        Node<E> p = node.right;

        if (p != null) {
            while (p.left != null) {
                p = p.left;
            }
            return p;
        }
    
        Node<E> parent = node.parent;
        while (parent != null && node == node.parent.right) {
            node = node.parent;
        }

        return node.parent;
    }

整体代码

package com.jvm.letcode;

import java.util.LinkedList;
import java.util.Queue;

public class BinaryTree<E> {
    protected int size;
    protected Node<E> root;

    // 清空所有元素
    public void clear() {
        root = null;
        size = 0;
    }

    // 元素的数量
    public int size() {
        return size;
    }

    // 是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 前序遍历
     */
    public void preorder(Visitor<E> visitor) {
        preorderTraversal(root, visitor);
    }

    public void preorderTraversal(Node<E> node, Visitor<E> visitor) {
        if (node == null) return;

        preorderTraversal(node.left, visitor);
        preorderTraversal(node.right, visitor);
    }


    /**
     * 中旬遍历
     */
    public void inorder(Visitor<E> visitor) {
        inorder(root, visitor);
    }

    public void inorder(Node<E> node, Visitor<E> visitor) {
        if (node == null) return;
        inorder(node.left, visitor);
        visitor.visit(node.element);
        inorder(node.right, visitor);

    }

    /**
     * 后续遍历
     */
    public void postorder(Visitor<E> visitor) {
        postorder(root, visitor);
    }

    public void postorder(Node<E> node, Visitor<E> visitor) {
        if (node == null) return;
        postorder(node.left, visitor);
        postorder(node.right, visitor);
        System.out.println("BinarySearchTree.inorderTraversal:" + node.element);
    }

    /**
     * 层序遍历
     */
    public void levelOrder(Visitor<E> visitor) {
        if (root == null || visitor == null) return;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            visitor.visit(node.element);
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }

    /**
     * 获取前驱节点
     *
     * @param node
     * @return
     */
    protected Node<E> predecessor(Node<E> node) {
        if (node == null) return null;
        Node<E> p = node.left;
        // 前驱节点在左子树当中 left.right.right.right
        if (p != null) {
            while (p.right != null) {
                p = p.right;
            }
            return p;
        }
        // 从父节点、祖父节点中国呢寻找前驱节点
        Node<E> parent = node.parent;
        while (parent != null && node == node.parent.left) {
            node = node.parent;
        }

        return node.parent;
    }

    /**
     * 获取后继节点
     *
     * @param node
     * @return
     */
    protected Node<E> successor(Node<E> node) {
        if (node == null) return null;
        Node<E> p = node.right;

        if (p != null) {
            while (p.left != null) {
                p = p.left;
            }
            return p;
        }

        Node<E> parent = node.parent;
        while (parent != null && node == node.parent.right) {
            node = node.parent;
        }

        return node.parent;
    }

    public Integer hight() {
        return hight(root);
    }

    public int hight(Node<E> node) {
        if (node == null) return 0;
        return 1 + Math.max(hight(node.left), hight(node.right));
    }

    public Integer hight2() {
        if (root == null) return 0;
        Queue<Node<E>> queue = new LinkedList<>();
        int queueSize = 1;
        int hight = 0;
        queue.offer(root);
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            queueSize--;
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
            if (queueSize == 0) {
                queueSize = queue.size();
                hight++;
            }
        }
        return hight;
    }

    public boolean isComplete() {
        if (root == null) return false;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        boolean leaf = false;
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();

            if (leaf && !node.isLeaf()) return false;

            if (node.hasTwoChildren()) {
                queue.offer(node.left);
                queue.offer(node.right);
            } else if (node.left == null && node.right != null) {
                return false;
            } else {
                // 判断是否都是叶子节点
                leaf = true;
                if (node.left != null) {
                    queue.offer(node);
                }
            }
        }
        return true;
    }

    public boolean isCompleteOther() {
        if (root == null) return false;
        Queue<Node<E>> queue = new LinkedList<>();
        queue.offer(root);
        boolean leaf = false;
        while (!queue.isEmpty()) {
            Node<E> node = queue.poll();
            if (leaf && !node.isLeaf()) return false;
            if (node.left != null) {
                queue.offer(node.left);
            } else if (node.right != null) {
                //node.left == null && node.right!=null,
                return false;
            }
            if (node.right != null) {
                queue.offer(node.right);
            } else {
                //node.left !=null && node.right==null 或者 node.left ==null && node.right == null
                leaf = true;
            }
        }
        return true;
    }


    public Object root() {
        return root;
    }

    public Object left(Object node) {
        return ((Node<E>) node).left;
    }

    public Object right(Object node) {
        return ((Node<E>) node).right;
    }

    public Object string(Object node) {
        return ((Node<E>) node).element;
    }

    /**
     * 遍历接口
     *
     * @param <E>
     */
    public static interface Visitor<E> {
        void visit(E element);
    }

    protected static class Node<E> {
        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        public Node(E element, Node<E> parent) {
            this.element = element;
            this.parent = parent;
        }

        public boolean isLeaf() {
            return left == null && right == null;
        }

        public boolean hasTwoChildren() {
            return left != null && right != null;
        }
    }
}
package com.jvm.letcode;

/**
 * 二叉搜索树
 *
 * @param <E>
 */
public class BinarySearchTree<E> extends BinaryTree {

    private Comparator<E> comparator;

    public BinarySearchTree(Comparator<E> comparator) {
        this.comparator = comparator;
    }

    // 添加元素
    public void add(E element) {
        elementNotNullCheck(element);
        if (root == null) {
            // 添加第一个节点
            root = new Node<>(element, null);
            size++;
            return;
        }
        // 添加不是第一个节点
        // 找到父节点
        Node<E> parent = null;
        Node<E> node = root;
        int cmp = 0;
        while (node != null) {
            cmp = compare(element, node.element);
            parent = node;
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) { // 新加的元素比父节点小
                node = node.left;
            } else { // 相等 将对象覆盖
                node.element = element;
                return;
            }
        }

        // 看看插入到副节点的哪个位置
        Node<E> newNode = new Node<>(element, parent);
        if (cmp > 0) {
            parent.right = newNode;
        } else {
            parent.left = newNode;
        }
        size++;
    }

    private int compare(E element1, E element2) {
        return comparator.comparator(element1, element2);
    }

    // 删除元素
    public void remove(E elemet) {
        remove(node(elemet));
    }

    // 删除元素
    public void remove(Node<E> node) {

        if (node == null) return;
        size--;

        // 度为2的节点
        if (node.hasTwoChildren()) {
            // 找到后继节点
            Node<E> s = successor(node);
            // 用后继节点的值 覆盖度为2的节点的值
            node.element = s.element;
            // 删除后继节点
            node = s;
        }

        // 删除node节点(node的度必然是1 或者 0)
        Node<E> repalcement = node.left != null ? node.left : node.right;

        if (repalcement != null) { // node的度是1
            // 更改
            repalcement.parent = node.parent;
            if (node.parent == null) {// node的度是1 并且是根节点
                root = repalcement;
            } else if (node == node.parent.left) {
                node.parent.left = repalcement;
            } else if (node == node.parent.right) {
                node.parent.right = repalcement;
            }
        } else if (node.parent == null) {  // node的度是0 叶子节点 并且是根节点
            root = null;
        } else { // node的度是0 叶子节点 但不是根结点
            if (node == node.parent.right) {
                node.parent.right = null;
            } else {
                node.parent.left = null;
            }
        }
    }

    private Node<E> node(E element) {
        Node<E> node = root;
        while (node != null) {
            int cmp = compare(element, node.element);
            if (cmp > 0) {
                node = node.right;
            } else if (cmp < 0) { // 新加的元素比父节点小
                node = node.left;
            } else { // 相等 将对象覆盖
                return node;
            }
        }
        return null;
    }


    // 是否包含某元素
    public boolean contains(E element) {
        return node(element) != null;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        toString(root, sb, "");
        return sb.toString();
    }

    public void toString(Node<E> node, StringBuilder sb, String prefix) {
        if (node == null) return;
        toString(node.left, sb, prefix + "L---");
        sb.append(prefix).append(node.element).append("\n");
        toString(node.right, sb, prefix + "R---");
    }


    private void elementNotNullCheck(E element) {
        if (element == null) {
            throw new IllegalArgumentException("element must not be null");
        }
    }


    public static void main(String[] args) {
        Integer[] a = new Integer[]{7, 4, 9, 2, 1, 3, 5, 9, 8, 11, 10, 12};
        BinarySearchTree<Integer> bst = new BinarySearchTree<Integer>(new Comparator<Integer>() {
            @Override
            public int comparator(Integer e1, Integer e2) {
                return e1 - e2;
            }
        });

        for (Integer i : a) {
            bst.add(i);
        }

        System.out.println("BinarySearchTree.main:" + bst.hight2());
        System.out.println("BinarySearchTree.main:" + bst.hight());


        bst.levelOrder(new Visitor<Integer>() {
            @Override
            public void visit(Integer element) {
                System.out.println("_" + element + "_");
            }
        });
    }
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值