数据结构与算法——二叉搜索树 (java泛型类)

泛型类实现二叉搜索树(BinarySearchTree,BST树)

本文借鉴https://juejin.im/post/59f352d5f265da432f305f0d

一、完整代码

1 二叉搜索树的节点类

 

BinarySearchTreeNode<T> node 实现

 

  http://www.cnblogs.com/hugeNumber/articles/7840519.html

2 BinarySearchTree BST

public class BSTree<T extends Comparable<T>>{
    private BinarySearchTreeNode<T> head;//根节点
  //获得根
    NTreeNode<T> getHead(){
        return head;
    }
    //新建BSTree树
    public NTreeNode<T> Create(T[] data ){
        NTreeNode<T> root = null;
        for(T temp : data){
            root = Insert(root, temp);
        }
        head = (BinarySearchTreeNode<T>)root;
        return root;
    }
    //  10
    //  / \
    // 8  12
    //假设每个数据占2个//
    public void PrintTree(NTreeNode<T> root){

        if(root == null)return;
        BinarySearchTreeNode<T> symbol = new BinarySearchTreeNode<>();//标识节点
        int level = Height(root) - 1 ;//节点所在的层,从根为0层开始
        //满二叉树上,n层的节点数为2^n
        int leafNum = (int)Math.pow(2, level);//满二叉树叶子数(最低层)
        LLQueue<NTreeNode<T>> Q = new LLQueue<>();//新建二叉搜索树节点队列
        LLNode<NTreeNode<T>> temp;//注意泛型
        Q.enQueue(root);//根入队列
        //逐层
        for(int i=0; i <= level; i++){
            int num = (int)Math.pow(2, i);//每一层最多为2^n
            int length = Math.round(leafNum/(num +1));//int length = (leafNum -(num + 1))/(num + 1);
            //System.out.println(num);
            for(int j = 0; j < num; j++){ //每一层最多为2^n
                temp = Q.deQueue();//取队头
                //打印////////////////////////////
                for(int k = 0; k < length; k++){
                    System.out.print("//");
                }
                //队列中的节点为symbol,打印占位符//
                if(symbol.equals(temp.data)){ //temp.data == symbol
                    System.out.print("//");
                }else {//否则打印节点信息
                    T info = temp.data.getData();
                    System.out.print(info);//打印节点值
                }

                if(temp.data.getLeft() != null){
                    Q.enQueue(temp.data.getLeft());//左儿子入队列
                }else{
                    Q.enQueue(symbol);//压入一个空标志
                }
                if(temp.data.getRight() != null){
                    Q.enQueue(temp.data.getRight());//右儿子入队列
                }else{
                    Q.enQueue(symbol);
                }
            }
            //再打印些占位符/
            for(int k = 0; k < length; k++){
                System.out.print("//");
            }
            System.out.println();
        }
    }

    //逐层打印
    public void LevelPrint(BinarySearchTreeNode<T> root){
        if(root == null) return;
        else{
            LLQueue<BinarySearchTreeNode<T>> Q = new LLQueue<>();
            LLNode<BinarySearchTreeNode<T>> temp;
            Q.enQueue(root);
            while(!Q.IsEmpty()){
                temp = Q.deQueue();//取队头的值
                //Do something
                System.out.print(temp.data.getData()+"  ");//打印
                if(temp.data.getLeft() != null){
                    Q.enQueue(temp.data.getLeft());//左儿子入队列
                }
                if(temp.data.getRight() != null){
                    Q.enQueue(temp.data.getRight());//右儿子入队列
                }

            }
        }
    }
    //先根遍历
    public  void PreOrder(BinarySearchTreeNode<T> root){
        if(root != null){
            //Do something;
            System.out.print(root.getData()+"  ");
            PreOrder(root.getLeft());
            PreOrder(root.getRight());
        }
    }
    //中根遍历
    public  void InOrder(BinarySearchTreeNode<T> root){
        if(root != null){
            InOrder(root.getLeft());
            System.out.print(root.getData()+"  ");//Do something;
            InOrder(root.getRight());
        }
    }

    //后根遍历
    public   void PostOrder(BinarySearchTreeNode<T> root){
        if(root != null){
            PostOrder(root.getLeft());
            PostOrder(root.getRight());
            System.out.print(root.getData()+"  ");//Do something;
        }
    }

    //a大于b,返回1;a小于b,返回-1;a等于b,返回0;
    private int Compare(T a, T b){
        /* compareTo()
            如果指定的数与参数相等返回0。
            如果指定的数小于参数返回 -1。
            如果指定的数大于参数返回 1。
         */
        return a.compareTo(b);
    }

    //插入
    public NTreeNode<T> Insert(NTreeNode<T> root, T data){

        if(root == null){
            root = new BinarySearchTreeNode<>();
            root.setData(data);
            root.setLeft(null);
            root.setRight(null);
        }else{
            if(data.compareTo(root.getData()) >= 1){         //data > root.getData();
                root.setRight(Insert(root.getRight(), data));
            }else if(data.compareTo(root.getData()) <= -1){  //data > root.getData();
                root.setLeft(Insert(root.getLeft(), data));
            }else{      // 找到相同的点什么也不做;

            }
        }
        return root;
    }

    //得到二叉搜索树高度
    public int Height(NTreeNode<T> root){
        if(root == null){
            return 0;
        }
        return ( Height(root.getLeft()) > Height(root.getRight()) ?  Height(root.getLeft()) : Height(root.getRight()) ) + 1;
    }

    //最小值节点,最左的叶子
    public NTreeNode<T> FindMin(NTreeNode<T> root){
        if(root == null){ //判断第一次进入的根
            return null;
        }
        if(root.getLeft() == null){
            return root;
        }else{
            return FindMin(root.getLeft());
        }
    }

    //删除节点
    public NTreeNode<T> Delete(NTreeNode<T>root, T data){
        BinarySearchTreeNode<T> rightMin;
        if(root == null)
            System.out.println("Element not there in tree!");//没有找到data的节点
        else if (Compare(data, root.getData()) >= 1) {
            root.setRight(Delete(root.getRight(), data));
        }else if(Compare(data, root.getData()) <= -1){
            //root.setLeft(Delete(root.getLeft(), data));
            BinarySearchTreeNode<T> temp = (BinarySearchTreeNode<T>)Delete(root.getLeft(), data);
            root.setLeft(temp);
        }else {
            //找到节点
            if (root.getLeft() != null && root.getRight() != null) {

                rightMin = (BinarySearchTreeNode<T>)FindMin(root.getRight());//找出右子树最小值
                root.setData(rightMin.getData());//右子树最小值替换当前节点值
                root.setRight(Delete(root.getRight(), rightMin.getData()));

            }else if(root.getLeft() == null && root.getRight() == null){ //不填这支就错误
                root = null;
            }else{
                //单支或叶子节点[这样可以令左右孩子都为null]
                if(root.getLeft() == null){
                    root = root.getRight();
                }
                if(root.getRight() == null){
                    root = root.getLeft();
                }

            }
        }
        return root;
    }
}

 查看Queue<T>实现点击

http://www.cnblogs.com/hugeNumber/articles/7840441.html

二 综合测试

1 测试用例

    public static void main(String[] args){
        System.out.println("start ====================");
        Integer[] A = {14,5,20,9,41,13,25,17,8,33,3,12,7,1,21,31};
        BSTree<Integer> mSearchTree = new BSTree<>(10);
        mSearchTree.Create(A);


        /*
        //二叉搜索树的高度
         System.out.println(mSearchTree.Height(root));
         */

        /*
        //删除一个节点
        Integer in = new Integer(10);
        mSearchTree.Delete(root, in);
        */
        /*
        System.out.println(mSearchTree.FindMin(root.getLeft().getLeft()).getData());//找出根左子树的左子树最小值
        System.out.println(mSearchTree.FindMin(root.getRight()).getData());//找出根右子树最小值
        */

        //打印
//        mSearchTree.PreOrder(root);
//        System.out.println();
//        mSearchTree.InOrder(root);
//        System.out.println();
//        mSearchTree.PostOrder(root);

//        mSearchTree.PrintTree(root);
////        mSearchTree.LevelPrint(root);
//        System.out.println("Delete a Node ===============");
//        mSearchTree.Delete(root, 13);
//        //逐层打印
//        mSearchTree.PrintTree(root);
    //逐层打印  
        mSearchTree.PrintTree(mSearchTree.getHead());
//        mSearchTree.LevelPrint(root);
        System.out.println("Delete a Node ===============");
        mSearchTree.Delete(mSearchTree.getHead(), 13);//删除某一节点
        //逐层打印
        mSearchTree.PrintTree(mSearchTree.getHead());
}

 2 结果展示

图1 creatTree

图2 删除节点13后

 

图3 二叉搜索树的高度(根为1算起)

 

posted @ 2017-11-15 18:59  倪明  阅读(204)  评论(0)    收藏  举报