在Java中从txt文件创建树

在Java中从txt文件创建树,java,data-structures,tree,Java,Data Structures,Tree,我应该使用以下类在Java中实现树数据结构: public class Tree<T extends Comparable<T>> { private TreeNode<T> root; public Tree(TreeNode<T> root) { this.root = root; } public void findChild(T data) { ... } public v

我应该使用以下类在Java中实现树数据结构:

public class Tree<T extends Comparable<T>>
{
    private TreeNode<T> root;

    public Tree(TreeNode<T> root)
    {
        this.root = root;
    }

    public void findChild(T data) { ... }
    public void findSibling(T data){ ... }
    public void printProgeny() { .. }
    public static Tree<String> createProgeny(String file) { ... }

    ...
}



public class TreeNode<T extends Comparable <T>>
{
    public T data;
    public TreeNode<T> parent;
    public TreeNode<T> leftChild;
    public TreeNode<T> rightSibling;

    ...
}
其中,行中的第一个字符串是以下字符串的父字符串。 这就是我挣扎的地方

假设我将第一行拆分,以便与[亚当、雅各布、汉娜、莎拉]形成一个数组。如何使用给定的方法从中创建子树

我认为,一旦我知道如何创建树并正确设置指针,其他方法就不会那么难实现

谢谢你的帮助

编辑: 这棵树看起来像这样

      Adam
  /    |    \
Jacob Hannah Sarah 
      /    \
    Esther  Abel
             |
            David
。。。或在Knuth变换之后:

    Adam
   /
 Jacob
    \
   Hannah
    /    \
 Esther  Sarah
     \
    Abel
    /
  David

您可以在方法中创建具有签名的递归函数,如
TreeNode makeTree(T[]data)

  • 创建一个新的
    TreeNode
    以返回
  • 将节点的
    数据
    设置为数组中的第一个元素
  • 将其余元素拆分为兄弟组和子组
  • 对这两个子组调用
    makeTree()
    函数,前提是它们不是空的
  • 在原始节点上,将子节点和同级节点设置为返回的节点
  • 将返回节点的父节点设置为原始节点
  • 最后返回原始节点
  • 您可以使用
    映射
    存储已创建的节点:

    BufferedReader br = //.. this is your file reader
    
    Map<String, TreeNode<String>> stringToTreeNode = new HashMap<>();
    TreeNode<String> root = null;
    String line;
    
    while ((line = br.readLine()) != null) {
        String[] lineParts = line.split(" ");
        int oldSize = stringToTreeNode.size();
        TreeNode<String> parent = getOrCreateTreeNode(stringToTreeNode, lineParts[0]);
        if (oldSize != stringToTreeNode.size()) {
             // new parent node created
    
             // in the end the root is the only node without a parent
             root = parent;
        }
        if (lineParts.length > 1) {
            // create children
            TreeNode<String> child = getOrCreateTreeNode(stringToTreeNode, lineParts[1]);
            parent.leftChild = child;
            child.parent = parent; 
            for (int i = 2; i < lineParts.length; i++) {
                TreeNode<String> nextChild = getOrCreateTreeNode(stringToTreeNode, lineParts[i]);
                nextChild.parent = parent;
                child.rightSibling = nextChild;
                child = nextChild;
            }
        }
    }
    Tree<String> result = new Tree<String>(root);
    
    BufferedReader br=/。。这是你的文件阅读器
    Map stringToTreeNode=新HashMap();
    treenoderoot=null;
    弦线;
    而((line=br.readLine())!=null){
    String[]lineParts=line.split(“”);
    int oldSize=stringToTreeNode.size();
    TreeNode父节点=getOrCreateTreeNode(stringToTreeNode,lineParts[0]);
    if(oldSize!=stringToTreeNode.size()){
    //已创建新的父节点
    //最后,根节点是唯一没有父节点的节点
    根=父;
    }
    如果(lineParts.length>1){
    //创造孩子
    TreeNode子节点=getOrCreateTreeNode(stringToTreeNode,lineParts[1]);
    parent.leftChild=child;
    child.parent=parent;
    对于(int i=2;i
    将此函数用作辅助函数:

    static TreeNode<String> getOrCreateTreeNode(Map<String, TreeNode<String>> map, String key) {
        TreeNode<String> result= map.get(key);
        if (result== null) {
             result = new TreeNode<>();
             result.data = key;
             map.put(key, result);
        }
        return result;
    }
    
    静态树节点getOrCreateTreeNode(映射映射,字符串键){
    TreeNode结果=map.get(键);
    如果(结果==null){
    结果=新的TreeNode();
    result.data=key;
    地图。放置(键、结果);
    }
    返回结果;
    }
    
    您的方法返回的
    void
    是不寻常的。我只能假设,
    findChild()
    在对象中设置光标,而不是返回节点。这不是我喜欢的风格。你应该确保你确实知道它应该如何工作(例如,它如何传达“未找到”?)-或者与你的导师澄清

    伪代码是:

    foreach line of text
        read parent name and list of children
        tree.findChild(parent)
        if not found, create root node with name of parent
        foreach child
            create new node and add as child of parent
                (by assigning to left-child to the parent...
                 ... or assigning to right-sibling of the previous child)
    
    有多种方法可以重新安排。例如,您可以构建一个孤立的孩子列表:

     Node siblingList = new Node(first child)
     Node tail = head
     while(more children)
         newChild = new Node(next child)
         tail.rightSibling = newChild
         tail = newChild
    
    。。。然后将该子项列表附加到相应的父项

     parent.leftChild = siblingList
    

    我想
    TreeNode
    也应该有
    rightChild
    成员。拥有
    rightsbibling
    意味着什么?这是左边的吗?IMHO
    TreeNode
    应该由数据、leftChild、rightChild和可选的父成员组成。你能用一些ASCII艺术来更新这个问题吗?最终结果数据结构是什么?我不清楚“Sarah”是“Hannah”节点的子节点还是“Adam”节点的子节点。@j3ny4任何树都可以表示为二叉树,只使用leftChild和rightSibling指针()@WalterWhite Ok。现在我明白了。所以,如果你的问题是关于一种特定类型的树(左子右兄弟二叉树),请清楚地说明。但是,您绘制的树不是二叉树(Adam有树的子树)。
     parent.leftChild = siblingList