Java 将具有多个值的地图转换为树?

Java 将具有多个值的地图转换为树?,java,algorithm,data-structures,tree,hierarchy,Java,Algorithm,Data Structures,Tree,Hierarchy,给定一组随机分布的键,每个键映射到一组值,如何将其转换为多棵树 示例数据集 NB2=>{NC2 ND2} ND1=>{NG1 NH1} NA1=>{NB1} NB1=>{NC1 ND1 NE1} NA2=>{NB2} NC1=>{NF1} NE1=>{NI1 NJ1 NK1} NA1的结果树 NA1 `--NB1 |--NC1 |`--NF1 |--ND1 ||--NG1 |`--NH1 `--NE1 |--NI1 |--NJ1 `--NK1 NA2生成树 钠 `--NB2 |--NC2 `

给定一组随机分布的键,每个键映射到一组值,如何将其转换为多棵树

示例数据集

  • NB2=>{NC2 ND2}
  • ND1=>{NG1 NH1}
  • NA1=>{NB1}
  • NB1=>{NC1 ND1 NE1}
  • NA2=>{NB2}
  • NC1=>{NF1}
  • NE1=>{NI1 NJ1 NK1}
NA1的结果树

NA1 `--NB1 |--NC1 |`--NF1 |--ND1 ||--NG1 |`--NH1 `--NE1 |--NI1 |--NJ1 `--NK1 NA2生成树

钠 `--NB2 |--NC2 `--钕
当你谈论将它们转换为一组树时,你是在谈论在内存中表示它们的方法吗

或者是我们将遍历您的一组键和值并将它们放入内存表示的算法


或者你说的是图形化表示?

我不知道有任何库方法可以实现这种转换。我会这样做的。这很简单,依我看

public class Tree {
    public Tree(String key) {
        // ...
    }
    public void addChild(Tree child) {
        // ...
    }
}

public Set<Tree> transform(Map<String, List<String>> input) {
    // Potential tree roots.  We start with all LHS keys as potential roots,
    // and eliminate them when we see their keys on the RHS.
    Set<String> roots = new HashSet<String>(input.keySet());

    // This map associates keys with the tree nodes that we create for them
    Map<String, Tree> map = new HashMap<String, Tree>();

    for (Map.Entry<String, List<String>> entry : input.entrySet()) {
        String key = entry.getKey();
        List<String> childKeys = entry.getValue();
        Tree tree = map.get(key);
        if (tree == null) {
            tree = new Tree(key);
            map.put(key, tree);
        }
        for (String childKey : childKeys) {
            roots.remove(childKey);
            Tree child = map.get(childKey);
            if (child == null) {
                child = new Tree(childKey);
                map.put(childKey, child);
            }
            tree.addChild(child);
        }
    }
    Set<Tree> res = new HashSet<Tree>(roots.size());
    for (String key : roots) {
        res.add(map.get(key));
    }
    return res;
}
公共类树{
公共树(字符串键){
// ...
}
公共void addChild(树子级){
// ...
}
}
公共集转换(映射输入){
//潜在树根。我们从所有LHS键作为潜在树根开始,
//当我们在RHS上看到他们的钥匙时就把他们除掉。
Set root=新的HashSet(input.keySet());
//此映射将键与我们为其创建的树节点相关联
Map Map=newhashmap();
for(Map.Entry:input.entrySet()){
String key=entry.getKey();
List childKeys=entry.getValue();
Tree-Tree=map.get(key);
if(tree==null){
树=新树(键);
地图。放置(键、树);
}
for(字符串childKey:childKey){
根。删除(childKey);
Tree child=map.get(childKey);
if(child==null){
child=新树(childKey);
map.put(childKey,child);
}
树。addChild(child);
}
}
Set res=新的HashSet(root.size());
for(字符串键:根){
res.add(map.get(key));
}
返回res;
}
编辑:注意,如果输入表示一组DAG(有向无环图),则此算法将“起作用”。然而,我刚刚意识到,生成的一组树将共享输入数据中任何公共子树的TreeNode实例


请注意,我尚未调试此代码:-)

这取决于您需要在树上执行的操作。你需要对树做什么?在这种情况下,Stephen C的解决方案,正如他所说的,是非常直接的(所以我投票支持他的答案——顺便说一句,一旦添加了树的方法,它就会起作用)。顺便说一句,你没有说你想如何处理自行车。Stephen的解决方案默默地省略了循环,但如果需要的话,抛出一个异常将是一件简单的事情。@Thangalin:我已经更新了我的答案,说出了DAG首字母缩略词代表什么。基本上,DAG是一棵树,子节点可以共享,但没有循环(循环)。 NA2 `-- NB2 |-- NC2 `-- ND2
public class Tree {
    public Tree(String key) {
        // ...
    }
    public void addChild(Tree child) {
        // ...
    }
}

public Set<Tree> transform(Map<String, List<String>> input) {
    // Potential tree roots.  We start with all LHS keys as potential roots,
    // and eliminate them when we see their keys on the RHS.
    Set<String> roots = new HashSet<String>(input.keySet());

    // This map associates keys with the tree nodes that we create for them
    Map<String, Tree> map = new HashMap<String, Tree>();

    for (Map.Entry<String, List<String>> entry : input.entrySet()) {
        String key = entry.getKey();
        List<String> childKeys = entry.getValue();
        Tree tree = map.get(key);
        if (tree == null) {
            tree = new Tree(key);
            map.put(key, tree);
        }
        for (String childKey : childKeys) {
            roots.remove(childKey);
            Tree child = map.get(childKey);
            if (child == null) {
                child = new Tree(childKey);
                map.put(childKey, child);
            }
            tree.addChild(child);
        }
    }
    Set<Tree> res = new HashSet<Tree>(roots.size());
    for (String key : roots) {
        res.add(map.get(key));
    }
    return res;
}