如何正确修复二进制树的读取,排序和计数?我如何使用分隔符作为重载构造函数,或者作为另一种方法,或者在我的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
答案 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很短,但它会跳过错误检查,数据隐藏等等。