1

Javaを使用してSystem.inにパイプされた文字列入力からバイナリツリーを構築しようとしています。文字列にazからの文字が含まれる場合は常に、内部ノード(2つの子を持つ)を作成しています。文字列で0が検出されるたびに、外部ノード(リーフ)を作成します。文字列はプレオーダーであるため、例として、次のような入力があった場合:

abcd000e000

次の二分木を作ることになっています

            a
           / \
          b   0
         / \
        c   e
       / \ / \
      d  00   0
     / \
    0   0

少なくとも、それは私が割り当ての詳細(以下のリンクにある)に従って作成することになっていると私が思うものです。プログラム全体のサンプル入力と出力も提供されました。

入力

a0
0
a00
ab000

出力

ツリー1:
無効です!
ツリー2:
高さ:-1
パス長:0
完了:はい
ポストオーダー:
ツリー3:
高さ:0
パス長:0
完了:はい
ポストオーダー:a
ツリー4:
高さ:1
パス長:1
完了:はい
ポストオーダー:ba

Javaでこれを行うプログラムを実装しようとしていますが、バイナリツリーを正しく作成していないと思います。私はこれまでに思いついたコードを提供し、デバッグ中にこれまでに遭遇した問題を各メソッドの上のコメントで詳しく説明しました。より多くのコンテキストが必要な場合は、次のリンクで割り当て全体と最終的な目標を詳しく説明します(バイナリツリーの構築は最初のステップにすぎませんが、私はそれに固執しています)。

割り当てへのリンク

import java.io.*;

// Node
class TreeNode {
    char value;
    TreeNode left;
    TreeNode right;
}

// Main class
public class btsmall {
    // Global variables
    char[] preorder = new char[1000];
    int i = 0;

    // Main method runs gatherOutput
    public static void main(String[] args) throws IOException {
        new btsmall().gatherOutput();
    }

    // This takes tree as input from the gatherOutput method
    // and whenever a 0 is encountered in the preorder character array
    // (from a string from System.in) a new external node is created with
    // a value of 0. Whenever a letter is encountered in the character
    // array, a new internal node is created with that letter as the value.
    //
    // When I debug through this method, the tree "appears" to be made
    // as expected as the tree.value is the correct value, though I 
    // can't check the tree.left or tree.right values while debugging
    // as the tree variable seems to get replaced each time the condition
    // checks restart.
    public void createTree(TreeNode tree) throws IOException {
        // Check that index is not out of bounds first
        if (i >= preorder.length) {
            i++;
        } else if (preorder[i] == '0') {
            tree = new TreeNode();
            tree.value = '0';
            tree.left = tree.right = null;
            i++;                
        } else {
            tree = new TreeNode();
            tree.value = preorder[i];
            i++;
            createTree(tree.left);
            createTree(tree.right);
        }
    }

    // Supposed to print out contents of the created binary trees.
    // Intended only to test that the binary tree from createTree()
    // method is actually being created properly.
    public void preorderTraversal(TreeNode tree) {
        if (tree != null) {
            System.out.println(tree.value + " ");
            preorderTraversal(tree.left);
            preorderTraversal(tree.right);
        }
    }

    // Reads System.in for the Strings used in making the binary tree
    // and is supposed to make a different binary tree for every line of input
    //
    // While debugging after the createTree method runs, the resulting tree variable
    // has values of tree.left = null, tree.right = null, and tree.value has no value
    // (it's just a blank space).
    //
    // This results in preorderTraversal printing out a single square (or maybe the square
    // is some character that my computer can't display) to System.out instead of all 
    // the tree values like it's supposed to...
    public void gatherOutput() throws IOException {
        InputStreamReader input = new InputStreamReader(System.in); 
        BufferedReader reader = new BufferedReader(input);

        String line = null;
        TreeNode tree = new TreeNode();
        while ((line = reader.readLine()) != null) {
            preorder = line.toCharArray();
            createTree(tree);
            preorderTraversal(tree);
            i = 0;
        }
    }
}

誰かがバイナリツリーを適切に構築するのを手伝ってくれて、私が現在得ている出力につながる間違っていることを指摘できますか?私は少なくとも正しい方向に進んでいますか?ヒントはありますか?

ありがとう。

編集:b これが「正方形」の出力の写真です(これはEclipseにあります)。

4

4 に答える 4

3

あなたのcreateTree()メソッドは...ツリーを作成しません。

内部ノードを何かに接続することは決してありません...ノードを作成し、値を挿入してから、次の呼び出しに渡しますcreateTree()(これは同じことを行います)。

于 2011-05-06T02:56:34.513 に答える
2

createTree(..)クイックフィックスは、メソッドの簡単な変更です。

public void createTree(TreeNode tree) throws IOException {
    // Check that index is not out of bounds first
    if (i >= preorder.length) {
        i++;
    } else if (preorder[i] == '0') {
        tree.value = '0';
        tree.left = tree.right = null;
        i++;                
    } else {
        tree.value = preorder[i];   
        i++;
        tree.left = new TreeNode();
        createTree(tree.left);
        tree.right = new TreeNode();
        createTree(tree.right);
    }
}

TreeNodeこのメソッドの内部を作成しているのに、すでに引数として渡されていることに注意してください。だから、あなたはまったく同じものを使用していませんでした。あなたがしたことは、元のTreeNodeパスにはありませんでした。

注意: 二分木の正しさについては議論していません。手元の問題を修正するだけです。これはOPに役立つ可能性があります。

于 2011-05-06T03:06:07.213 に答える
1

しかし、私は二分木を正しく作っているとは思いません

はい、それは正しくありません。二分木では、1つのサブツリーは現在の要素より「少ない」、もう1つのサブツリーは「多い」です。たとえば、「c」と「e」の親として「b」がありますが、(自然ソートに従う場合)「c」と「e」はどちらも「more」です。

その過程でツリーのバランスを取り直す必要があります。

PS入力でゼロが何を意味するのかわかりませんが、入力が制限されている場合、ソートされたシーケンスからバイナリツリーを構築する最も簡単な方法は次のとおりです。

  1. シーケンス全体を配列にロードします
  2. ルート要素として中間要素を取得します
  3. ルート要素の左右のサブ配列に対して、手順2を再帰的に繰り返します。

アップデート

そして、はい、他のいくつかの答えで述べられているように、あなたは次のようなものを持っている必要があります:

    } else if (preorder[i] == '0') {
        TreeNode subTree = new TreeNode();
        subTree.value = '0';
        tree.rigth = subTree;
        i++;  

次に、subTreeを再帰呼び出しに渡します。

于 2011-05-06T02:58:20.503 に答える
1

また、実装の問題があります。

    while ((line = reader.readLine()) != null) {

正しい停止状態ではないようです。Enterキーを押すだけで、行はnullではなく、空の文字列になるため、永久にループします。

これがより適しています:

    while (!(line = reader.readLine()).equals("")) {
于 2011-05-06T03:15:04.737 に答える