[英]BinaryTree in Java - build words and display it
我對大學有一個我想不通的問題。 我有一個文件,其中包含構建二叉樹的說明
r a
rr b
rl c
rrr h
rrl i
rlr j
rll k
d
l e
ll f
lr g
lll l
llr m
lrl n
lrr o
r - 右,l - 左,要打印的內容。 “d”是根
我加載文件,將每一行分成指令和一個值,但我不知道下一步該做什么——我被卡住了。
我必須構建一棵樹並使用遞歸來解決它......並打印來自樹狀“hbad”、“kcad”、“lfed”等的所有單詞......
我現在的代碼:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int i = 0;
String key[] = new String[2];
String root = "";
ArrayList<String> lineFile = new ArrayList<String>();
Scanner scan = null;
try {
scan = new Scanner(new File("tree.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (scan.hasNextLine()) {
lineFile.add(scan.nextLine());
}
for (i = 0; i < lineFile.size(); i++) {
if (lineFile.get(i).length() > 1) {
key = lineFile.get(i).split(" ");
System.out.print(key[0] + " " + key[1]);
} else {
root = lineFile.get(i);
}
System.out.println(" " + lineFile.get(i).length());
}
System.out.println(root);
}
}
請幫助...任何示例實現,鏈接或其他...
如上所述,二叉樹由一組節點組成。 每個節點有兩個子節點,left 和 right,它們也是節點。 一個簡單的節點實現可能如下所示:
public class BinaryTreeNode<T> {
private final T value;
private BinaryTreeNode<T> left;
private BinaryTreeNode<T> right;
public BinaryTreeNode(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public BinaryTreeNode<T> getLeft() {
return left;
}
public void setLeft(BinaryTreeNode<T> left) {
this.left = left;
}
public BinaryTreeNode<T> getRight() {
return right;
}
public void setRight(BinaryTreeNode<T> right) {
this.right = right;
}
}
這個版本是通用的,但您可以將 value 設置為 String 並讓生活更輕松。 從根值創建樹的基礎:
BinaryTreeNode<String> tree = new BinaryTreeNode<>(root);
解析您的輸入並將其添加到樹中比較棘手。 為了簡化一點,我創建了一條新指令 class,每行的兩部分(位置和值)分開。 為了方便起見,我做了一個內部 class (不需要getter/setter),但這不是必需的:
private class Instruction {
String node;
String value;
public Instruction(String node, String value) {
this.node = node;
this.value = value;
}
}
創建指令列表:
List<Instruction> instructions = new ArrayList<>();
並將其填充到您的循環中:
instructions.add(new Instruction(key[0], key[1]));
現在進行遞歸加載。 這可能不是最好的解決方案,但它有效:
private void buildSubTree(BinaryTreeNode node, List<Instruction> instructions) {
// Get the left branch
List<Instruction> left = instructions.stream()
.filter(i -> i.node.startsWith("l"))
.collect(Collectors.toList());
// Get the right branch
List<Instruction> right = instructions.stream()
.filter(i -> i.node.startsWith("r"))
.collect(Collectors.toList());
// Find the first left instruction
Instruction firstLeft = left.stream().filter(i -> i.node.length() == 1).findFirst().orElse(null);
// Find the first right instruction
Instruction firstRight = right.stream().filter(i -> i.node.length() == 1).findFirst().orElse(null);
if (firstLeft != null) {
// Set the left child
node.setLeft(new BinaryTreeNode(firstLeft.value));
// Find left children by reducing instruction node String (remove first character)
List<Instruction> leftChildren = left.stream().map(i -> new Instruction(i.node.substring(1), i.value)).collect(Collectors.toList());
// Recursively build left branch
buildSubTree(node.getLeft(), leftChildren);
}
if (firstRight != null) {
// Set the right child
node.setRight(new BinaryTreeNode(firstRight.value));
// Find right children by reducing instruction node String (remove first character)
List<Instruction> rightChildren = right.stream().map(i -> new Instruction(i.node.substring(1), i.value)).collect(Collectors.toList());
// Recursively build right branch
buildSubTree(node.getRight(), rightChildren);
}
}
構建樹:
buildSubTree(tree, instructions);
該方法將在給定節點(第一次調用中的根節點)下構建兩個子樹,並使用每個子節點和每一側的簡化指令集遞歸調用自身。 可以在此處進行一些改進,使指令 class 更有幫助。
從列表中構建單詞更容易:
private List<String> buildWordsFromTreeLeafUp(BinaryTreeNode<String> startNode) {
// List of words to return
List<String> words = new ArrayList<>();
// First populate the list with words from each child branch
if (startNode.getLeft() != null) {
words.addAll(buildWordsFromTreeLeafUp(startNode.getLeft()));
}
if (startNode.getRight() != null) {
words.addAll(buildWordsFromTreeLeafUp(startNode.getRight()));
}
// Add the startNodes value to each word
words = words.stream().map(s -> s + startNode.getValue()).collect(Collectors.toList());
// Add the value as a word of it's own
words.add(startNode.getValue());
return words;
}
我敢打賭,這不是最優雅的實現,但它完成了工作。
如果您只想要完整長度(4 個字母)的單詞,這里是單詞構建方法最后一部分的替代方法:
if (words.isEmpty()) {
// Add the value as a word of it's own
words.add(startNode.getValue());
} else {
// Add the startNodes value to each word
words = words.stream().map(s -> s + startNode.getValue()).collect(Collectors.toList());
}
編輯
上面的最后一個代碼塊可以替換 buildWordsFromTreeLeafUp() 中的等效行。 這是它的工作原理:
該方法寫入所有單詞,一次一個字母,但針對每個單詞。
在上面的第一個實現中,我們也將當前字母添加為新單詞。 這樣,除了所有 4 個字母的單詞之外,我們還將獲得所有 3 個和 2 個字母的單詞(從樹的中間某處開始)以及一個僅包含根元素的 1 個字母的單詞 ('d')。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.