【问题标题】:How to build an n-ary tree having same structure as another created one?如何构建与另一个创建的具有相同结构的 n 叉树?
【发布时间】:2021-05-17 15:35:44
【问题描述】:

我正在尝试构建这个与已经构建的具有相同结构的 n 元树(在创建要返回的新树时,我想将子节点添加到与已经构建的树相同的位置,构建的树创建如下:

        Node A = new Node("","A");
        Node B = new Node("","B");
        Node C = new Node("","C");
            ...


        Node root = A;
        root.children.add(B);
        root.children.add(C);
        root.children.add(D);

        root.children.get(1).children.add(G);
        root.children.get(1).children.get(0).children.add(K);
              ...

节点类如下:

public class Node {

    public String id;
    public ArrayList<ArrayList<String>> data;
    public Vector<Node> children = new Vector<>();

    public void setId(String id) {
        this.id = id;
    }

    public void setData(ArrayList<ArrayList<String>> data) {
        this.data = data;
    }


    public void setChildren(Vector<Node> children) {
        this.children = children;
    }

    public Node(ArrayList<ArrayList<String>> data, String id) {
        this.data = data;
        this.id = id;
    }
    public Node(ArrayList<ArrayList<String>> data,String id,Vector<Node> children) {
        this.data = data;
        this.id = id;
        this.children = children;
    }

    public Node find_parentNode(String childId) {
        if (this == null)
            return null;

        Queue<Node> queue = new LinkedList<>();
        // we add start node
        queue.add(this);

        // iterate while queue not empty
        while (!queue.isEmpty()) {
            // dequeue and print data
            Node next = queue.remove();
            

            for (Node child : next.children) {
              if (child.id == childId)
                return next;
                queue.add(child);
            }
        }
        return null;
    }

最后主要代码如下:

       // Create rootOut (the root node to be returned)
       Node rootOut = new Node(node.data,node.id,node.children);

       queue.add(node);


        // iterate while queue not empty
        while(!queue.isEmpty()){
            // dequeue
            Node next = queue.remove();
            // we add children nodes if not null after setting an increment var for the children positions
            int j =0 ;
            for (Node child : next.children) {
                
                // Update children of rootOut (the output Tree)
                Node currentNode = rootOut.find_parentNode(child.id);

                currentNode.children.get(j).setChildren(child.children);
                currentNode.children.get(j).setData(child.data);
                currentNode.children.get(j).setId(child.id);
                j++;
                queue.add(child);
            }
        }

基本上在主代码中,在将旧的构建树复制到新树之后(通过根节点rootOut),我覆盖了构建树的节点的值,而不是创建新树, 这是一个好方法吗?否则如何创建与构建树具有相同结构(节点位置)的全新树?

谢谢。

【问题讨论】:

    标签: java data-structures tree nodes search-tree


    【解决方案1】:

    要复制现有树的结构,只需进行深度优先遍历,复制每个节点并以相同的遍历顺序添加每个子节点。

    您不需要找到父节点,这是一个昂贵的搜索,因为该节点将在之前的方法调用中添加到正确的父节点。

    我无法测试您的代码,因为缺少某些内容(例如 QueryNode 是什么?),但它似乎只复制了根节点,而没有实际复制树结构。

    所以这个方法会递归地复制树,新老树之间唯一共享的资源就是数据ArraList,这里只复制引用。

    public static Node cloneNode(Node root) {
        Node copy=new Node(root.data, root.id);
        for (Node c: root.children) {
            copy.children.add(cloneNode(c)));
        }
        return copy;
    }
    

    作为对您最后一个 cmets 的回答,数据的深层副本并不常见,但如果您真的想要它,只需将方法的第一行替换为以下内容:

    ArrayList<ArrayList<String>> copyData=new ArrayList<>();
    for (ArrayList<String> l: root.data) {
        copyData.add(new ArrayList<String>(l));
    }
    Node copy=new Node(copyData, root.id);
    

    一些不相关的言论:

    1. 不要使用 Vector,而是使用 ArrayList
    2. 在方法签名和变量声明中,最好使用具体 ArrayList 类的 List 接口(例如,数据应声明为 List

    【讨论】:

    • 我在我的方法中采用复制,但这是一个好方法吗?我想创建一个新树并将节点添加到正确的位置(根据构建的树),这将是一个更好的方法,但是感谢您的回答它有点帮助
    • 比我这里的台词好:Node rootOut = new Node(node.data,node.id,node.children);
    • @PatrickSchulz 我不确定您的代码是否正常工作,因为您没有复制子向量,而是在两棵树之间共享它,所以最后您只复制了根节点.我的代码是在复制结构,而不是数据,如果您还想复制数据,请制作数据的深层副本。
    • 你能展示如何制作数据的深层副本吗?我也正在通过以下方式复制数据:currentNode.children.get(j).setChildren(child.children); currentNode.children.get(j).setData(child.data); currentNode.children.get(j).setId(child.id);
    • @PatrickSchulz setData(child.data) 只是复制对数据的引用,即列表列表,如果您修改数据的内容,您也会在复制的节点中看到更改。
    猜你喜欢
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 2021-12-15
    • 2020-05-04
    相关资源
    最近更新 更多