简体   繁体   English

如何在Java中创建动态树数据结构

[英]How to create dynamic tree data structure in Java

specifically I need to represent the following: 具体来说,我需要代表以下内容:

  1. The tree at any node can have an arbitrary number of children 任何节点上的树都可以有任意数量的子代
  2. Each parent node (after the root) is just a String (whose children are also Strings) 每个父节点(在根之后)只是一个字符串(其子代也是字符串)
  3. I need to be able to get parent and list out all the children (some sort of list or array of Strings) given an input string representing a given node 我需要能够获得父代,并列出代表给定节点的输入字符串,列出所有子代(某种形式的列表或字符串数​​组)
  4. Dynamically populating the tree structure based on reference relationship between parent and child. 根据父级和子级之间的引用关系动态填充树结构。 Example given is I have one member1 sponsor another member2, and member2 sponsor member 3 and so and so for. 给出的示例是我有一个member1赞助者另一个member2,而member2赞助者成员3等等。 Already have the table records relationship 已经有表记录关系

Is there an available structure for this ??? 有没有可用的结构呢?

像图像中那样建造一棵树

My data is from DB or a List, I will loop through the information with the name and the relation to determine if the node is a root, parent or a child. 我的数据来自数据库或列表,我将遍历具有名称和关系的信息,以确定该节点是根节点,父节点还是子节点。

So during the loop, I found a child, I need a reference to the parent so that I can compare the child relation to the parent before adding the child to its parent. 因此,在循环中,我找到了一个孩子,我需要引用父对象,以便在将孩子添加到其父对象之前可以将其与父对象的关系进行比较。

The closest code I found . 我找到的最接近的代码。

public class TreeNode<T> implements Iterable<TreeNode<T>> {

    T data;
    TreeNode<T> parent;
    List<TreeNode<T>> children;

    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
    }

    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }

    // other features ...

}
Sample usage:

TreeNode<String> root = new TreeNode<String>("root");
{
    TreeNode<String> node0 = root.addChild("node0");
    TreeNode<String> node1 = root.addChild("node1");
    TreeNode<String> node2 = root.addChild("node2");
    {
        TreeNode<String> node20 = node2.addChild(null);
        TreeNode<String> node21 = node2.addChild("node21");
        {
            TreeNode<String> node210 = node20.addChild("node210");
        }
    }
}

This is what I have done so far. 到目前为止,这是我所做的。 The parent will get overwritten by the latest entry so hence I am unable to retrieve what I have added previously . 父项将被最新条目覆盖,因此我无法检索之前添加的内容。

public static TreeNode<String> getSet1() throws IOException {

        BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
        String line;

        while ((line = reader.readLine()) != null) {
            String[] items = line.split(":");

            String name = items[0];
            String parent = items[1];
            String type = items[2];

            if (parent.equalsIgnoreCase("-") && type.equalsIgnoreCase("mainparent")) {

                root = new TreeNode<String>(name);


            } else if (type.equalsIgnoreCase("ChildParent")  && parent.equalsIgnoreCase(root.toString())) {

                childParent = root.addChild(name);

           } else if (type.equalsIgnoreCase("Child") && parent.equalsIgnoreCase(childParent.toString())) {

                child = childParent.addChild(name);
            }

        }

        return root;
    }

Your diagram indicates a tree of arbitrary depth, but your code only handles grandparent -> parent -> child relationships (with a single grandparent at the root). 您的图表示一棵任意深度的树,但是您的代码仅处理祖父母->父->子关系(在根中有一个祖父母)。

I would ignore the type, as all you need is the name of a person and the name of their parent. 我会忽略类型,因为您所需要的只是一个人的名字和他们父母的名字。 If the parent name is a dash, you know you have the root. 如果父名称是破折号,则说明您拥有根。

Now for each person, you need to get the parent node already in the tree (assuming parents come before children in the list - if that's not the case, the problem becomes significantly more complex, as you would have to store orphaned persons temporarily and for each new person see if they are the parent of an orphaned person). 现在,对于每个人,您都需要在树中已有父节点(假设父节点在列表中的子节点之前-如果不是这样,问题将变得更加复杂,因为您将不得不暂时存储孤儿,每个新人都看他们是否是孤儿的父母)。

In order to get the parent by name, you should store each person you have already processed in a second data structure, parallel to the tree. 为了按名称获取父级,您应该将已经处理过的每个人存储在与树平行的第二个数据结构中。 The second data structure should make it easy to look someone up by name. 第二个数据结构应使按名称查找某人变得容易。 Maps, and in particular Hashtables, are ideal for this. 地图,尤其是哈希表非常适合此操作。 This is how it works: 它是这样工作的:

Map processedPersonsMap=new Hashtable<String, TreeNode<String>>();

For each person, you store them in the map, indexed by their name: 对于每个人,您都将它们存储在地图中,并按其名称索引:

TreeNode<String> person=...;
processedPersonsMap.put(person.getData(), person);

When you read in a new person and their parent's name is not a dash, you look up the parent: 当您读一个新的人并且他们父母的名字不是破折号时,您会查找父母:

String parentName=items[1];
TreeNode<String> parent=processedPersonsMap.get(parentName);

In this way, no matter how deep the tree is, you will always find the right parents. 这样,无论树有多深,您总会找到合适的父母。 However, keep in mind that this requires a valid input file where each child comes after their parent, and which does not contain circular references or missing parents. 但是,请记住,这需要一个有效的输入文件,每个孩子都位于其父母之后,并且不包含循环引用或缺少父母。

If those conditions are not met, you have to handle them explicitly. 如果不满足这些条件,则必须明确处理它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM