二叉搜索树的 java 代码实现

12 篇文章 0 订阅
2 篇文章 0 订阅

代码

package erchashu;

//二叉树要求所有项都能排序,使用Comparable接口表示任何两项都可以用compareTo方法比较
//另一种方法是使用Comparator
public class BinarySearchTree<Type extends Comparable<? super Type>> {
    //嵌套类,定义二叉树结点
    private static class BinaryNode<Type> {
        Type data;
        BinaryNode<Type> leftChild;
        BinaryNode<Type> rightChild;

        BinaryNode( Type data ) {
            this( data, null, null );
        }

        BinaryNode( Type d, BinaryNode<Type> l, BinaryNode<Type> r ){
            data = d; leftChild = l; rightChild = r;
        }
    }

    //根节点   
    private BinaryNode<Type> root;

    //若干私有方法
    private boolean contains( Type x, BinaryNode<Type> r ) {
        if ( r == null ) return false;

        if ( r.data.compareTo(x) > 0 ) 
            return contains( x, r.leftChild );
        else if ( r.data.compareTo(x) < 0 )
            return contains(x, r.rightChild);
        else return true;
    }

    private Type findMin( BinaryNode<Type> r ) { 
        while ( r.leftChild != null ) {
            r = r.leftChild;
        }
        return r.data;
    }

    private Type findMax( BinaryNode<Type> r ) {
        while ( r.rightChild != null) { r = r.rightChild; }

        return r.data;
    }

    private BinaryNode<Type> recursiveInsert( Type x, BinaryNode<Type> r ) {
        //此节点为空,也是数据该插入的地方,返回一个新建节点
        if ( r == null ) return new BinaryNode<Type>( x );

        if ( r.data.compareTo(x) > 0 ) 
            r.leftChild = insert(x, r.leftChild );
        else if ( r.data.compareTo(x) < 0 )
            r.rightChild = insert(x, r.rightChild );
        else ;          //do nothing

        //将插入后的新树赋给旧树
        return r;
    }

    private void print( BinaryNode<Type> r , int deepth ) {  
        if ( r != null ) {
            for ( int i = 0; i < 2*deepth; i++) 
                System.out.print(" ");
            System.out.println(r.data.toString());

            print( r.rightChild, deepth + 1);
            print( r.leftChild, deepth + 1);
        }
    }

    private BinaryNode<Type> remove( Type x, BinaryNode<Type> r ) {
        if ( r.data.compareTo( x ) > 0 ) 
            r.leftChild = remove( x , r.leftChild );
        else if ( r.data.compareTo( x ) < 0 ) 
            r.rightChild = remove( x , r.rightChild );
        //表示已确定该节点
        else if ( r.rightChild == null && r.leftChild == null ) 
            return null;
        else if ( r.rightChild == null || r.leftChild == null) 
            return (r.rightChild == null ? r.leftChild : r.rightChild);
        else {
            BinaryNode<Type> t = r.rightChild;
            while ( t.leftChild != null ) t = t.leftChild;
            r.data = t.data;

            r.rightChild = remove( r.data, r.rightChild );
        }

        return r;
    }

    //构造
    public BinarySearchTree() { root = null; }

    //清空树
    public void makeEmpty() { root = null; }

    //判断树是否为空
    public boolean isEmpty() { return root == null; }

    //判断是否二叉树包含x (实在不知道该是什么异常)
    public boolean contains( Type x ) throws Exception {
        if ( isEmpty() ) 
            throw new Exception();      
        return contains( x, root);
    }

    //查找最小项
    public void findMin() throws Exception {
        if ( isEmpty() ) 
            throw new Exception();      
        System.out.print( findMin( root ) + " ");
    }

    //查找最大项
    public void findMax() throws Exception {
        if ( isEmpty() ) 
            throw new Exception();  
        System.out.print( findMax( root ) + " ");
    }

    //递归插入节点
    public void recursiveInsert( Type x ) { root = recursiveInsert( x, root ); }

    //非递归实现
    public void insert( Type x ) throws Exception {
        if ( root == null ) {
            root = new BinaryNode<Type> (x);
        } else {
            BinaryNode<Type> i = root;     // i和root的引用的对象相同

            while ( true) {
                if ( x.compareTo(i.data) > 0 && i.rightChild == null) {
                    i.rightChild = new BinaryNode<Type> (x);
                    break;
                } else if ( x.compareTo(i.data) > 0 ) {
                    i = i.rightChild;
                } else if ( x.compareTo(i.data) < 0 && i.leftChild == null) {
                    i.leftChild =  new BinaryNode<Type> (x);
                    break;
                } else if( x.compareTo(i.data) < 0 )  {
                    i = i.leftChild;
                } else return;
            }
        }
        print();
    }

    //删除节点
    public void remove( Type x ) throws Exception {
        if ( isEmpty() ) 
            throw new Exception();  
        root = remove(x, root);

        print();
    }

    //打印树
    public void print() throws Exception {
        if ( isEmpty() ) 
            throw new Exception(); 
        print(root, 0);
        System.out.println();
    }

    public static void main( String [] args ) throws Exception {
        BinarySearchTree<Integer> binarySearchTree = new BinarySearchTree<>();
        binarySearchTree.insert(5);
        binarySearchTree.insert(2);
        binarySearchTree.insert(3);
        binarySearchTree.insert(7);
        binarySearchTree.insert(6);
        binarySearchTree.insert(8);
        binarySearchTree.insert(1);
        binarySearchTree.insert(0);
        binarySearchTree.insert(4);
        binarySearchTree.insert(9);

        binarySearchTree.remove(5);
        binarySearchTree.remove(2);

        binarySearchTree.findMax();
        binarySearchTree.findMin();
    }
}

输出

(把树右转九十度,方便观察)

5

5
  2

5
  2
    3

5
  7
  2
    3

5
  7
    6
  2
    3

5
  7
    8
    6
  2
    3

5
  7
    8
    6
  2
    3
    1

5
  7
    8
    6
  2
    3
    1
      0

5
  7
    8
    6
  2
    3
      4
    1
      0

5
  7
    8
      9
    6
  2
    3
      4
    1
      0

6
  7
    8
      9
  2
    3
      4
    1
      0

6
  7
    8
      9
  3
    4
    1
      0

9 0 

简要分析

在一棵高度为 h 的二叉搜索树上,从代码易知删除、搜索等都可以在 O( h ) 时间完成,但二叉搜索树容易产生左右不平衡现象。所以我要去学更高级的树了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CHOOOU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值