输入文件中的二叉树问题

时间:2015-06-30 20:08:37

标签: java algorithm binary-tree nodes delimiter

如何正确修复二进制树的读取,排序和计数?我如何使用分隔符作为重载构造函数,或者作为另一种方法,或者在我的main方法中使用?

这是我需要使用的当前输入文件:

      A
   /     \
  B        C
   \     /  \
    D   E    F
   /     \
  G       H
 /      /   \
I      J     K

表示上述树的当前文件是TreeFile.txt,其序列表示缺少的节点:

A
B
C
NULL 
D
E
F
NULL
NULL
G
NULL 
NULL
H
NULL
NULL
NULL
NULL
NULL
NULL
I
NULL
NULL
NULL
NULL
NULL
J
K
NULL
NULL
NULL
NULL

但是如果我使用这个文本文件,那么它将通过我在我的代码中使用的算法来创建并显示预订,有序,后订单和级别顺序,节点计数的树,叶子计数,左边和右边的节点数量。在我的代码中可以纠正什么,以便不显示“NULL”,排序和计数也显示正确?

我的代码,它接受输入并使树具有预订样本并计算左侧节点:

import java.util.Scanner;

public class BinaryTree<E> {

private class NodeClass<E> {

    private NodeClass<E> left;
    private NodeClass<E> right;
    private E value;

    public NodeClass(E value) {

        left = null;
        right = null;
        this.value = value;
    }

}

private NodeClass<E> root;

// confusion here
public BinaryTree(Scanner scan) throws Exception {

    NodeClass<E> currentNode = root;
    NodeClass<E> nextNode = null;

    while (scan.hasNextLine()) {

        String value = (String) scan.nextLine().trim();

        if (value.length() == 0)
            continue;

        if (root == null) {

            root = new NodeClass(value);

        } else {

            currentNode = root;
            nextNode = currentNode;

            while (nextNode != null) {

                if (nextNode.left == null) {

                    insertingLeft(nextNode, (E) value);
                    break;

                } else if (nextNode.right == null) {

                    insertingRight(nextNode, (E) value);
                    break;
                }

                if (nextNode == currentNode) {

                    nextNode = currentNode.left;

                } else if (nextNode == currentNode.left) {

                    nextNode = currentNode.right;

                } else if (nextNode == currentNode.right) {

                    nextNode = currentNode.left.left;
                    currentNode = currentNode.left;

                }

            }

        }

    }

}

public void insertingRight(NodeClass<E> Node, E element) {

    if (Node.right == null) {

        Node.right = new NodeClass<E>(element);

    } else {

        insertingRight(Node.right, element);

    }
}

public void insertingLeft(NodeClass<E> Node, E element) {

    if (Node.left == null) {

        Node.left = new NodeClass<E>(element);

    } else {

        insertingLeft(Node.left, element);

    }
}

public BinaryTree() {

    root = null;

}

public String PreOrder() {

    StringBuilder builder = new StringBuilder();

    PreOrder(builder, root);

    return builder.toString();

}

private void PreOrder(StringBuilder builder, NodeClass<E> node) {

    builder.append(" " + node.value.toString());
    if (node.left != null) {

        PreOrder(builder, node.left);

    }

    if (node.right != null) {

        PreOrder(builder, node.right);

    }

}

public int leftCount() {

    return leftCount(root);

}

private int leftCount(NodeClass<E> node) {

    int count = 0;

    if (node.left != null && node.right == null) {

        count++;
        count += leftCount(node.left);

    }

    if (node.right != null) {

        count += leftCount(node.right);

    }

    return count;

}
}

我的主要驱动程序类:

import java.io.File;
import java.util.Scanner;

public class testBinaryTree {

public static void main(String[] args) {

    try {

        Scanner in = new Scanner(new File("TreeFile.txt"));
        BinaryTree<String> bt = new BinaryTree<String>(in);

        System.out.print("Pre Order: " + bt.PreOrder() + "\n");
        System.out.println("Left Count: " + bt.leftCount());

    } catch (Exception ex) {

        ex.printStackTrace();

    }

}

}

显示回来:

Pre Order:  A B NULL NULL NULL NULL I NULL NULL NULL NULL NULL NULL NULL J K NULL NULL NULL H NULL NULL NULL NULL NULL D G NULL C E F
Left Count: 0

2 个答案:

答案 0 :(得分:0)

显示您的“NULL”节点,因为您实际创建了包含文本“NULL”的节点,并且在打印预订单输出时不考虑它们。

您可以在打印预订时过滤那些文本为“NULL”的节点并忽略它们(与忽略实际为null的节点相同)。

或者,我认为更好,不是从头开始插入它们。但是,这需要您跟踪插入位置。我认为最简单的方法是先将整个节点列表放在一个数组中,然后然后从中创建树。有一些公式可以计算一个节点的左或右子节点的索引(左子的2 * i + 1,右子的2 * i + 2),可以帮助你找到合适的孩子。

首先,只需将所有字符串读入数组String[] nodes,然后在其上调用BuildTreeFromArray(0, nodes)即可构建树:

NodeClass<E> BuildTreeFromArray(int index, String[] nodes) {
    if (index >= nodes.length) {
        return null;
    } else {
        NodeClass<E> node = new NodeClass<E>(nodes[index]);
        node.left = BuildTreeFromArray(2 * index + 1, nodes);
        node.right = BuildTreeFromArray(2 * index + 2, nodes);
        return node;
    }
}

答案 1 :(得分:0)

我强烈建议您在输入文件中使用更好的树形表示。例如,使用三元组列表,每个三元组将父级链接到其子级。然后顺序无关紧要(除了使第一个节点成为root),你可以忽略所有不存在的节点:

A B C
B - D
D G -
G I -
C E F
E - H
H J K

然后使用节点字典构建树很容易:

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class TreeBuilder {
  Map<String, Node> valToNode = new HashMap<>();

  static class Node {
    String key;
    Node left, right;

    Node(String key) { this.key = key; }

    void printTree() {
      System.out.print(key);
      if (left != null || right != null) {
        System.out.print("(");
        print(left);
        System.out.print(", ");
        print(right);
        System.out.print(")");
      }
    }

    static void print(Node node) {
      if (node == null) 
        System.out.print("-");
      else 
        node.printTree();
    }
  }

  Node buildTree(String filePath) throws IOException  {
    Node root = null;
    for (String line : Files.readAllLines(
        Paths.get(filePath), Charset.forName("UTF-8"))) {
      String[] vals = line.split("\\s+");
      Node parent = lookupOrCreateNode(vals[0]);
      parent.left = lookupOrCreateNode(vals[1]);
      parent.right = lookupOrCreateNode(vals[2]);
      if (root == null) root = parent;
    }
    return root;
  }

  Node lookupOrCreateNode(String key) {
    if ("-".equals(key)) return null;
    Node node = valToNode.get(key);
    if (node == null) {
      node = new Node(key);
      valToNode.put(key, node);
    }
    return node;
  }

  void run() {
    try {
      Node tree = buildTree("src/hacking/data.txt");
      tree.printTree();
      System.out.println();
    } catch (IOException ex) {
      System.err.println("input file not found");
    }
  }

  public static void main(String[] args) {
    new TreeBuilder().run();
  }
}

输出:

A(B(-, D(G(I, -), -)), C(E(-, H(J, K)), F))

注意:java很短,但它会跳过错误检查,数据隐藏等等。