2

最初に、Java でのジェネリック型の使用法について検索しましたが、見つけた答えはあまりにも単純または複雑でした。だからここに私の正確な質問があります。

それぞれPerfectTreeControl、Tree、およびEntryの3つのクラスがあります。

ツリーは

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> 親の違いは何ですか? 整数、文字列、または私が望むものとして使用できることは知っていK element ますが、同じことがオブジェクトにも当てはまりますか? パラメータなしで Entry 変数を使用しようとしましたが、 Entry は生の型であり、パラメータ化する必要があり、エラーなしで動作しているとしか言いませんでした。

2 番目の質問は、ツリーが完全かどうかをチェックすることです。これまでに試したいくつかのコードは次のとおりです。

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 を and で試してみましたが、やはり違いはありませんでした。コードが正しく動作せず、完全に混乱しています。
4

1 に答える 1

3

Java のジェネリックは、基本的に、そのオブジェクトが宣言されるまでどのクラスかを認識して、オブジェクト内の特定のクラスに名前を付ける方法です。これは、コンパイラがそのクラスへの参照間で一貫性を確保できるため便利です。

より具体的には、クラス内Entry<K>で を参照するたびKに、Java コンパイラは、 type のすべての参照がK実際には type として扱われるように強制しますK。たとえば、 type のオブジェクトを作成する場合、そのオブジェクトEntry<String>のメンバーは type でなければならず、メンバーはtype でなければならないなどです。 を返すメソッドがあった場合、コンパイラは戻り値が であることを認識します。コンパイラがここに矛盾を見つけた場合 (たとえば、の値を anに設定しようとした場合)、エラーが発生します。 elementStringparentEntry<String>KStringmemberInteger

上記の例で説明した品質はすべて、Entry<String>定義した特定のオブジェクトに関連していることに注意してください。代わりに を定義するEntry<Integer>と、クラスを更新せずEntryに、その新しいオブジェクト内で一貫性が強制されますが、今回はK意味のあるInteger.

の型引数を指定せずにオブジェクトを作成するとK、「生の型」が使用されます。これにより、コンパイラは整合性ルールを適用できなくなり、 の型が であると想定されKますObject。これは、適切に行うのが面倒なキャスティングについて心配し始める必要があることを意味します。

ツリーがいっぱいかどうか (または「完全」かどうか) を確認するための最も直感的な方法は、再帰的な方法です。このシナリオで使用する再帰的なルールは、「ツリーの子が完全で深さが同じであれば、ツリーは完全である」です。

于 2012-06-30T22:43:21.107 に答える