递归填充树形图

时间:2012-01-02 10:01:53

标签: java

我有一个数据结构,其中节点可以有多个父节点 我有一个我想插入树的节点列表。 列表中的节点包含数据及其父节点的子列表。

我想从这个列表中构建一个树。

private class Treenode {

        private List<Treenode> children;
        private List<Treenode> parents;

        public List<Treenode> getChildren() {
            return children;
        }

        public List<Treenode> getParents() {
            return parents;
        }

        private Info data;


        public Info getData() {
            return data;
        }

        public void setData(Info data) {
            this.data = data;
        }

        public Treenode() {
            children = new ArrayList<Treenode>();
            parents = new ArrayList<Treenode>();
        }

        public Treenode(Info data) {
            children = new ArrayList<Treenode>();
            parents = new ArrayList<Treenode>();
            this.data = data;
        }

        public boolean addChild(Treenode n) {
            return children.add(n);
        }

        public boolean removeChild(Treenode n) {
            return children.remove(n);
        }
        public boolean addParent(Treenode n) {
            return parents.add(n);
        }

        public boolean removeParent(Treenode n) {
            return parents.remove(n);
        }



    }


private void scanListAndAddToTree(final List list,Treenode parent){

        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Info info = (Info) iter.next();
            String [] parents = info.getParents();
            if(parents==null){ //no parents
                Treenode newNode = new Treenode(info);
                parent.addChild(newNode);
                scanTree(list,newNode);
            } else

            for (int i = 0; i < parents.length; i++) {
                if (parents[i].getID.equals(parent.data.getID())){
                    Treenode newNode = new Treenode(info);
                    parent.addChild(newNode);
                    scanTree(list,newNode);
                }
            }           

}

但我的代码错了:(

递归永远不会停止并重新添加相同的节点

1 个答案:

答案 0 :(得分:3)

如果按照以下方式制作课程防弹,则按项目完成的列表插入没有问题。

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class GraphNode<D> {

    private D data;
    private Set<GraphNode<D>> ins = new HashSet<>();
    private Set<GraphNode<D>> outs = new HashSet<>();

    public GraphNode(D data) {
        this.data = data;
    }

    public D getData() {
        return data;
    }

    public void setData(D data) {
        this.data = data;
    }

    public Set<GraphNode<D>> getIns() {
        return Collections.unmodifiableSet(ins);
    }

    public Set<GraphNode<D>> getOuts() {
        return Collections.unmodifiableSet(outs);
    }

    public void addIn(GraphNode<D> node) {
        if (node == null) {
            throw new NullPointerException(); // Never add null.
        }
        if (ins.add(node)) {
            node.outs.add(this);
        }
    }

    public void addOut(GraphNode<D> node) {
        if (node == null) {
            throw new NullPointerException(); // Never add null.
        }
        if (outs.add(node)) {
            node.ins.add(this);
        }
    }
}

备注

  • 这是用Java 7编写的,用于较早的Java更改<><GraphNode<D>>
  • 我使用了名称Graph,与多个父亲一样,Tree是用词不当。
  • Info类参数化为<D>,以便可以重复使用该类。
  • 收藏品的吸气剂无法修改。
  • addIn和addOut garantuee一个正确的结构。
  • removeIn / removeOut“left as excercise”。
  • 我使用Set依赖于Object(指针)相等。

public static class Info {
    private String id;
    private String[] parents;

    private String getID() {
        return id;
    }

    public String[] getParents() {
        return parents;
    }
}

public static class TreeNode extends GraphNode<Info> {
    public TreeNode(Info info) {
        super(info);
    }
}

private void insertGraph(Map<String, TreeNode> allNodes, List<Info> insertList) {
    for (Info info : insertList) {
        TreeNode newNode = new TreeNode(info);
        allNodes.put(info.getID(), newNode);
    }
    for (TreeNode node : allNodes.values()) {
        for (String parentID: node.getData().getParents()) {
            TreeNode parentNode = allNodes.get(parentID);
            parentNode.addOut(node);
        }
    }
}

private TreeNode scanTree(Info rootInfo, List<Info> insertList) {
    Map<String, TreeNode> allNodes = new HashMap<>();
    insertList.add(rootInfo);
    insertGraph(allNodes, insertList);
    return allNodes.get(rootInfo.getID());
}

由于无法保证单个树具有所有父项,并且Info已包含该结构,因此不需要递归,但需要一组节点。 由于Info可能引用未定义TreeNode的ID,因此需要两个阶段/ fors。