首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

泛型的二叉搜索树,请指点解决方案

2012-02-26 
泛型的二叉搜索树,请指点泛型的二叉搜索树,请指点小弟初学java,写了一个泛型的二叉搜索树(源代码见后)。IBS

泛型的二叉搜索树,请指点
泛型的二叉搜索树,请指点小弟初学java,写了一个泛型的二叉搜索树(源代码见后)。

IBSTree接口定义一个二叉搜索树的对外接口,这个接口描述了二叉搜索树的所有对外可见的行为。具体的方法描述见源代码的注释。

IBSTree接口中有定义了一个二叉搜索树的节点类型的接口IBSTNode(这个接口也可以在IBSTree接口的外部定义,只是这个接口太小,个人觉得没必要单独定义),

这个接口描述了二叉搜索树的一个节点的对外可以的部分(对外只是可以获取节点的值)。

然后再定义了两个类BSTNode和BSTree,分别实现了这两个接口。

这个设计有点复杂,自己都觉得不够清爽^-^,

定义IBSNode纯粹是考虑到实现的效率,返回一个IBSNode的类可以传达更多的节点信息,尽管这些信息对外不可见,但是内部实现需要这些信息。

二叉搜索树的各个操作的实现没有做注释^-^,是由于这些操作在任何一本数据结构的书上都有详细的说明。

小弟主要关注的是泛型和程序的整个结构。

请各位路过的大虾指点一下,小弟万分感激。^-^

小弟初来,没多少分,^-^

源文件共三个:IBSTree.java、BSTNode.java、BSTree.java。

文件1:IBSTree.java

package   BinarySearchTree;

//二叉搜索树类型
public   interface   IBSTree <Value   extends   Comparable <Value> >   {
       
        public   interface   IBSTNode <Value>   {
               
                Value   getValue();                                                         //获取二叉搜索树结点的键
               
                boolean   isEmpty();                                                         //判断二叉搜索树结点是否为空
               
        }
       
        void   makeEmptyBST();                                                         //创建一棵空的二叉搜索树
       
        boolean   isEmptyBST();                                                         //判断一棵二叉搜索树是否为空
       
        IBSTNode <Value>   search(Value   k);                                 //在二叉树搜索树中查找指定的键
       
        boolean   insert(Value   k);                                                 //向二叉搜索树中插入键
       
        IBSTNode <Value>   getMax();                                                 //获取二叉搜索树中的最大值
       
        IBSTNode <Value>   getMin();                                                 //获取二叉搜索树中的最小值
       
        IBSTNode <Value>   succ(IBSTNode <Value>   n);                 //获取后继


       
        IBSTNode <Value>   pred(IBSTNode <Value>   n);                 //获取前驱
       
        boolean   delete(IBSTNode <Value>   n);                                 //删除二叉搜索树中的指定元素  
       
}

文件2:BSTNode.java

package   BinarySearchTree;

/**
*BSTNode类表示二叉搜索树的一个结点。
*BSTNode的值可以是:
*     1、EMPTY。表示这是一个空结点。
*     2、(key,left,right,parent)。其中key表示结点值,left表示左子树,right表示右子树,parent表示父节点。  
*Value类型是一种实现了Comparable接口的类型。
*/
public   final   class   BSTNode <Value   extends   Comparable <Value> >  
        implements   IBSTree.IBSTNode <Value>   {
               
                public   Value   getValue()   {   //获取二叉搜索树结点的键

                        if   (this==EMPTY)   return   null;
                        else   return   this.key;
                }
               
                public   boolean   isEmpty()   {   //判断二叉搜索树结点是否为空

                        if   (this==EMPTY)   return   true;
                        else   return   false;
                }
               
                static   final   BSTNode   EMPTY=new   BSTNode(null,null,null,null);   //表示空的二叉树节点
                       
                BSTNode <Value>   left;
               
                BSTNode <Value>   right;
               
                BSTNode <Value>   parent;
               
                Value   key;
               
                BSTNode(Value   key,BSTNode <Value>   left,
                        BSTNode <Value>   right,BSTNode <Value>   parent)   {
                        this.key=key;
                        this.left=left;
                        this.right=right;
                        this.parent=parent;


                }                        
               
        }

文件3:BSTree.java

package   BinarySearchTree;

/**
*BSTree类表示二叉搜索树。
*Value类型是一种实现了Comparable接口的类型。
*/
public   final   class   BSTree <Value   extends   Comparable <Value> >  
        implements   IBSTree <Value>   {

        public   void   makeEmptyBST()   {//创建一棵空的二叉搜索树
                root=BSTNode.EMPTY;
        }
       
        public   boolean   isEmptyBST()         {//判断二叉搜索树结点是否为空
                if   (root==BSTNode.EMPTY)   return   true;
                else   return   false;
        }

        public   IBSTNode <Value>   getMax()   {//获取二叉搜索树中的最大值
                if   (root==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                else   {
                        BSTNode <Value>   p=root;
                        while   ((p!=BSTNode.EMPTY)&&(p.right!=BSTNode.EMPTY))
                                p=p.right;
                        return   p;
                }                        
        }

        public   IBSTNode <Value>   getMin()   {//获取二叉搜索树中的最小值
                if   (root==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                else   {
                        BSTNode <Value>   p=root;
                        while   ((p!=BSTNode.EMPTY)&&(p.left!=BSTNode.EMPTY))
                                p=p.left;
                        return   p;
                }                        
        }
       
        public   IBSTNode <Value>   search(Value   k)   {//在二叉树搜索树中查找指定的键
                BSTNode <Value>   p=root;
                while   ((p!=BSTNode.EMPTY)&&(p.key.compareTo(k)!=0))
                        if   (k.compareTo(p.key) <0)   p=p.left;


                        else   p=p.right;
                return   p;
        }

        public   boolean   insert(Value   k)   {//向二叉搜索树中插入键
                if   (root==BSTNode.EMPTY)   {
                        root=new   BSTNode <Value> (k,BSTNode.EMPTY,
                                BSTNode.EMPTY,BSTNode.EMPTY);
                        return   true;
                }   else   {
                        BSTNode <Value>   p=root;
                        BSTNode <Value>   q=root;
                        while   ((p!=BSTNode.EMPTY)&&(p.key.compareTo(k)!=0))
                                if   (k.compareTo(p.key) <0)   {
                                        q=p;
                                        p=p.left;
                                }   else   {
                                        q=p;
                                        p=p.right;
                                };
                        if   (p==BSTNode.EMPTY)   {
                                p=new   BSTNode <Value> (k,BSTNode.EMPTY,
                                        BSTNode.EMPTY,BSTNode.EMPTY);
                                if   (k.compareTo(q.key) <0)   q.left=p;
                                else   q.right=p;
                                return   true;
                        }   else   return   false;
                }
        }

        public   IBSTNode <Value>   succ(IBSTNode <Value>   n)   {//获取后继


                if   (!(n   instanceof   BSTNode))   return   BSTNode.EMPTY;
                BSTNode <Value>   m;
                m=(BSTNode <Value> )   n;
                if   (m==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                else   {
                        if   (m.right!=BSTNode.EMPTY)   {
                                BSTree <Value>   p=new   BSTree <Value> (m.right);
                                return   p.getMin();
                        }   else   {
                                BSTNode <Value>   p=m;
                                BSTNode <Value>   q=p.parent;
                                while   ((q!=BSTNode.EMPTY)&&(q.right==p))   {
                                        p=q;
                                        q=p.parent;
                                }
                                if   (q==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                                else   return   q;
                        }
                }                
        }

        public   IBSTNode <Value>   pred(IBSTNode <Value>   n)   {//获取前驱
                if   (!(n   instanceof   BSTNode))   return   BSTNode.EMPTY;
                BSTNode <Value>   m;
                m=(BSTNode <Value> )   n;
                if   (m==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                else   {
                        if   (m.left!=BSTNode.EMPTY)   {
                                BSTree <Value>   p=new   BSTree <Value> (m.left);
                                return   p.getMax();


                        }   else   {
                                BSTNode <Value>   p=m;
                                BSTNode <Value>   q=p.parent;
                                while   ((q!=BSTNode.EMPTY)&&(q.left==p))   {
                                        p=q;
                                        q=p.parent;
                                }
                                if   (q==BSTNode.EMPTY)   return   BSTNode.EMPTY;
                                else   return   q;
                        }
                }
        }

        public   boolean   delete(IBSTNode <Value>   n)   {//删除二叉搜索树中的指定元素   ,没实现
                return   true;
        }
       
        private   BSTNode <Value>   root;
       
        private   BSTree(BSTNode <Value>   root){
                this.root=root;
        }
}


[解决办法]
怎么说呢?可以说你的代码没什么错,因为它可以实现需要的功能;但也可以说,你的代码完全错了,因为它完全不像Java编程的方式,更像从C或C++“翻译”过来的。

我提几点供你参考:

首先,你的接口没什么存在的必要,因为它只有一个实现类,而且如果你的实现类已经实现了所有功能,别人没有理由按你定义的接口再去实现一个。
我想楼主是模仿C++中的做法,把类的接口都定义到头文件中,具体实现放到类实现文件中;但在Java中没有必要这样做。因为Java编译器会自动搜索现存的其它类,不需要一个类似于C++中的头文件那样的“中介”。换句话说,接口的“中介”作用是在运行时体现的,不是为了编译。

第二,你没有充分利用面向对象的特性,比如makeEmptyXXX()这样的接口,很容易让人联想到古老的C语言教程上的代码。
把初始化工作放到构造方法中,再设置一个用来执行清空动作的empty()方法(如果需要的话),这种作法更合理。

第三,二叉检索树是递归定义的,根据这个递归定义,很容易得到,一棵二叉检索树的左右子树(如果有的话)分别各是一棵二叉检索树。
再加上你的类是泛型的,泛型的类型就是节点的类型,所以,Node这个类没有什么存在的必要,换句话说,Node本身就是二叉检索树,二者可以合而为一。

第四,代码风格上的问题。
命名不是很符合Java的惯例,比如,包名应该从简,并且完全小写,而类名应该尽量详细并带有自说明性,一般不简写;Java的接口名一般不带字母“I”的前缀。当然这些不是什么大问题。

根据上面的几点考虑,我整理的代码如下:

(我的方法是递归的,递归的程序逻辑更清晰,当然,如果基于效率的考虑,不应该滥用递归;不过,仍旧可以先用递归方式设计出基本功能,再去对细部进行优化;
删除节点方法比较复杂,未实现)

Java code
package bst;public final class BinarySearchTree <T extends Comparable <T> > {    private T value;    private BinarySearchTree<T> parent;    private BinarySearchTree<T> left, right;    public boolean isEmpty() {        return value == null;    }    public boolean insert(T newValue) {        if (isEmpty()) {  //如果是空树,则直接对value赋值,并初始化左右子树            value = newValue;            left = new BinarySearchTree <T> ();            right = new BinarySearchTree <T> ();            left.parent = right.parent = this;            return true;        }        if (newValue.compareTo(value) > 0)  // 如果插入的值大于当前值,插在右子树中            return right.insert(newValue);        else if (newValue.compareTo(value) < 0)  // 如果插入的值小于当前值,插在左子树中            return left.insert(newValue);        return false;  // 节点已存在,插入失败    }    public boolean delete(T val) {        // 未实现    }        public T search(T val) {        if (!isEmpty()) {            if (val.compareTo(value) > 0)  // 如果待检索值大于当前值,检索右子树                return right.search(val);            else if (val.compareTo(value) < 0) // 如果待检索值小于当前值,检索左子树                return left.search(val);            else                return value; // 检索成功,返回当前值        }        return null;  // 检索失败,返回null    }        public T getMin() {        if (left.isEmpty())  // 如果左子树为空,则当前值最小            return value;        return left.getMin();  // 从左子树中找最小值    }        public T getMax() {        if (right.isEmpty())  // 如果右子树为空,则当前值最大            return value;        return right.getMax();  // 从右子树中找最大值    }        public String toString() {  // 显示该树,该方法可选        StringBuffer result = new StringBuffer();        if (!isEmpty()) {            result.append(value);            if (!left.isEmpty() || !right.isEmpty()) {                result.append('(');                result.append(left);                result.append(',');                result.append(right);                result.append(')');            }        }        else result.append('*');        return result.toString();    }} 

热点排行
Bad Request.