Невозможно правильно создать двоичное дерево? - PullRequest
1 голос
/ 06 мая 2011

Я пытаюсь построить двоичное дерево из строкового ввода, переданного в System.in с помощью Java.Всякий раз, когда в строке встречается буква от 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 ]

3 голосов
/ 06 мая 2011

Ваш createTree() метод ... не создает дерево.

Вы никогда не присоединяете внутренние узлы к чему-либо ... вы просто создаете их, вставляете значение, а затем передаете их следующему вызову createTree() (который делает то же самое).

2 голосов
/ 06 мая 2011

Быстрое исправление может быть простой модификацией вашего метода 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 пройдено.

NB: Не спорю о правильности двоичного дерева. Просто исправьте проблему в руке. Это может помочь ОП.

1 голос
/ 06 мая 2011

Также я вижу проблему реализации:

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

, похоже, не является правильным условием остановки.Это будет цикл навсегда, потому что если вы нажмете только ввод, строка будет не нулевой, а пустой строкой.

Этот больше подходит:

    while (!(line = reader.readLine()).equals("")) {
1 голос
/ 06 мая 2011

но я не думаю, что делаю двоичное дерево правильно

Да, это неверно. В двоичном дереве одно поддерево «меньше» текущего элемента, другое - «больше». Например, «b» является родительским для «c» и «e», в то время как (если следовать естественной сортировке) оба «c» и «e» являются «более».

Вам нужно перебалансировать свое дерево в процессе.

P.S. Я не знаю, что нули должны означать на входе, но если вход ограничен, самый простой способ построить двоичное дерево из отсортированной последовательности:

  1. загрузка всей последовательности в массив
  2. получить средний элемент в качестве корневого
  3. повторить шаг 2 рекурсивно для подмассивов слева и справа от корневого элемента

Обновление

И да, как указано в каком-то другом ответе, вам нужно что-то вроде:

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

, а затем передать поддерево в рекурсивный вызов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...