【问题标题】:Tree Implementation with Generic Types in Java在 Java 中使用泛型类型实现树
【发布时间】:2012-07-01 22:44:27
【问题描述】:

首先我搜索了 java 中泛型类型的用法,但是我发现的答案太简单或太复杂了。所以这是我的确切问题。

我有三个类,分别是 PerfectTreeControl、Tree 和 Entry。

树有

public class Tree<K> {
  public Entry <K> root;

条目有

public class Entry<K> {
    public K element;
    public Entry<K> parent, left_child, right_child;


    public Entry(K element) {
        this.element = element;
    }
    public Entry(K element, Entry<K> left, Entry<K> right) {
        left_child = left;
        right_child = right;
        this.element = element;
    }

我想了解 Entry 父级和 Entry 父级之间的区别是什么?我知道K element 可以用作整数、字符串或我想要的任何东西,但同样的事情也适用于对象吗?我尝试使用不带参数的 Entry 变量,它只说 Entry 是原始类型,应该参数化,它仍然可以正常工作。

我的第二个问题是关于检查一棵树是否完美。以下是我迄今为止尝试过的一些代码:

public class PerfectTreeControl {

    public static boolean isPerfect(Tree<String> tree) {
        Tree t1 = new Tree();
        if( t1.isFull( tree.root ) ) {  
            int depth = t1.height(tree.root);
            return t1.everyLeafHasSameDepth(tree.root, depth);
        } 
        else 
            return false;
    }   
    }





public class Tree<K> {
    public Entry <K> root;

    public boolean isLeaf(Entry e) {
        return e.left_child == null &&
                e.right_child == null;
    }

    public int height(Entry  e) {
        if( e == null ||
                e.left_child == null &&
                e.right_child == null ) 
            return  0;
        int left = height( e.left_child );
        int right = height( e.right_child );

        return 1 + Math.max(left, right);
    }

    public boolean isFull(Entry base) {
        if( isLeaf(base) )
            return true;
        else
            if( base.left_child != null && base.right_child != null ) {
                return isFull(base.left_child) &&
                        isFull(base.right_child);
            } else {
                return false;
            }
    }


    public  int depth(Entry e) {
        if( e == root ) {
            return 0;
        } else {
            return 1 + depth(e.parent);
        }
    }

    public  boolean everyLeafHasSameDepth(Entry base, int depth) {
        if( base == null ) 
            return false;
        else if(isLeaf(base) ) 
            return depth( base ) == depth;
        else {
            return 
                    everyLeafHasSameDepth(base.left_child, depth) &&
                    everyLeafHasSameDepth(base.right_child, depth);
        }
    }
  • 入口类(我写在页面顶部) 正如你所见,PerfectTreeControl类中的isPerfect方法使用Tree-String-tree作为参数,我不知道它是什么。在 Tree 类中,我尝试了 Entry 并且一次又一次没有区别。代码无法正常工作,我完全糊涂了。

【问题讨论】:

  • 您不应该真正担心原始类型。它们只是为了向后兼容而存在的,您永远不应该使用泛型类型的原始版本。 (即在您的代码中,到处使用Entry&lt;Something&gt;。)
  • 定义泛型对象的意义何在?更清楚地说,将对象定义为泛型而不是普通对象有什么好处?对象已经可以将您在类中定义的任何内容作为变量、字符串、int 等。我错过了什么吗?
  • @nihirus:如果您在任何地方都使用普通对象,那么每次您想做某事时都需要将值转换为所需的类型。
  • @nihirus 主要是类型安全。我强烈建议至少阅读臭名昭著的 Angelika Langer FAQ 的开头部分

标签: java generics binary-tree implementation


【解决方案1】:

从根本上说,Java 中的泛型是一种在对象中命名特定类的方法,在声明该对象之前知道哪个类。这很有用,因为它允许编译器在对该类的引用之间强制执行一致性。

更具体地说,在您的类Entry&lt;K&gt; 中,任何时候您引用K,Java 编译器都会强制所有K 类型的引用实际上都被视为K 类型。例如,如果您创建一个Entry&lt;String&gt; 类型的对象,则该对象的element 成员必须是String 类型,parent 成员必须是Entry&lt;String&gt; 类型等。如果您有一个方法返回K,编译器将识别出返回值为String。如果编译器在这里发现不一致 - 比如说,如果您尝试将 member 的值设置为 Integer - 它会抱怨。

请记住,我在上面的示例中描述的品质都是针对您定义的特定 Entry&lt;String&gt; 对象。如果您改为定义 Entry&lt;Integer&gt;,而不更新您的 Entry 类,则会在该新对象中强制执行一致性 - 除了这次 K 表示 Integer

如果您创建对象时没有为 K 指定类型参数,则您使用的是“原始类型”。这可以防止编译器强制执行一致性规则,它会假定K 的类型是Object。这意味着您将不得不开始担心演员阵容,这可能会很乏味。

要检查一棵树是否已满(或“完美”),最直观的方法是递归方法。在这种情况下使用的递归规则是“如果一棵树的孩子是完美的并且具有相同的深度,那么这棵树就是完美的。”

【讨论】:

    猜你喜欢
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多