首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

高分查询树形结构中某节点逆展开所有路径有关问题

2012-12-22 
高分求救查询树形结构中某节点逆展开所有路径问题比如有一个表结构 idparentchild A13 B23 C34 D54 E64 F7

高分求救查询树形结构中某节点逆展开所有路径问题
比如有一个表结构 

id    parent    child 
A     1         3 
B     2         3 
C     3         4 
D     5         4 
E     6         4 
F     7         5 
G     8         4 

如何取得所有root节点到节点4的所有路径的id 
放到map中,key为parent,value为list<id> 

如上表应该有5条路径 

1)     1 > 3 > 4    map.put(1 : C,A)
2)     2 > 3 > 4    map.put(2 : C,B)
3)     7 > 5 > 4    map.put(7 : F,D)
4)     6 > 4        map.put(6 : E)
5)     8 > 4        map.put(8 : G)

请大家帮忙解决一下,谢谢了。。。
[最优解释]
Map<Integer, List<String>> result = new HashMap<Integer, List<String>>();
Map<Integer, Integer> temp1 = new HashMap<Integer, Integer>();
temp1.put(1, 3);
temp1.put(2, 3);
temp1.put(3, 4);
temp1.put(5, 4);
temp1.put(6, 4);
temp1.put(7, 5);
temp1.put(8, 4);
Map<Integer, Integer> temp2 = new HashMap<Integer, Integer>();
temp2.put(3, 1);
temp2.put(3, 2);
temp2.put(4, 3);
temp2.put(4, 5);
temp2.put(4, 6);
temp2.put(5, 7);
temp2.put(4, 8);
Map<Integer, String> temp3 = new HashMap<Integer, String>();
temp3.put(1, "A");
temp3.put(2, "B");
temp3.put(3, "C");
temp3.put(5, "D");
temp3.put(6, "E");
temp3.put(7, "F");
temp3.put(8, "G");
Iterator<Integer> it = temp1.keySet().iterator();
while (it.hasNext()) {
Integer pid = it.next();
if (!temp2.containsKey(pid)) {
List<String> list = new ArrayList<String>();
result.put(pid, list);
list.add(temp3.get(pid));
Integer id = temp1.get(pid);
while (temp1.containsKey(id)) {
list.add(temp3.get(id));
id = temp1.get(id);
}
}
}
System.out.println(result);
result:{2=[B, C], 8=[G], 6=[E], 1=[A, C], 7=[F, D]}
为啥结果会不同?
[其他解释]
这种存储方式就是一个简单的链接表存储图的顶点和边,当然可以使用图搜索算法。
但是由于问题的简单性,可以直接使用深度搜索到目标的路径。

package com.tur.demo;

import java.util.*;

public class Hello {
    public static void main(String[] args) {
        /*
        id    parent    next
        A     1         3


        B     2         3
        C     3         4
        D     5         4
        E     6         4
        F     7         5
        G     8         4
        */
        List<String> paths = new ArrayList<String>();

        Pair target = new Pair(4, 0);
        Map<Integer, Pair> foo = new HashMap<Integer, Pair>();
        foo.put(1, new Pair(1, 3));
        foo.put(2, new Pair(2, 3));
        foo.put(3, new Pair(3, 4));
        foo.put(5, new Pair(5, 4));
        foo.put(6, new Pair(6, 4));
        foo.put(7, new Pair(7, 5));
        foo.put(8, new Pair(8, 4));

        for (Map.Entry<Integer, Pair> e : foo.entrySet()) {
            List<Pair> path = findPath(foo, e.getValue(), target);

            if (isValidPath(path, target)) {
                String pathStr = representPath(path);

                // 如果短路径在长路径中,去掉短路径
                boolean included = false;
                for (int i = 0; i < paths.size(); ++i) {
                    String str = paths.get(i);

                    if (str.endsWith(pathStr)) {
                        paths.set(i, str);
                        included = true;
                        break;
                    } else if (pathStr.endsWith(str)) {
                        paths.set(i, pathStr);


                        included = true;
                        break;
                    }
                }

                if (!included) {
                    paths.add(pathStr);
                }
            }
        }

        // 输出路径
        for (String path : paths) {
            System.out.println(path);
        }
    }

    /**
     * 判断给定的节点集合是否合法的路径
     * 注:更通用的做法是检查整个路径链是否合法,而不只是检查最后一个节点
     * @param path
     * @param target
     * @return
     */
    public static boolean isValidPath(List<Pair> path, Pair target) {
        return path.size() > 0 && target.equals(path.get(path.size() - 1));
    }

    /**
     * 深度搜索起始节点到目标节点的路径
     * @param foo 包含所有节点的集合
     * @param start 起始节点
     * @param target 目标节点
     * @return 返回起始节点到目标节点的路径
     */
    public static List findPath(Map<Integer, Pair> foo, Pair start, Pair target) {
        List<Pair> path = new ArrayList<Pair>();

        if (start == null) { return path; }

        do {
            path.add(start);
            start = foo.get(start.next);
        } while (start != null && !path.contains(target) && !path.contains(start));

        if (path.get(path.size() - 1).next == target.code) {
            path.add(target);
        }

        return path;
    }

    /**
     * 自定义路径的显示方式
     * @param path
     * @return


     */
    public static String representPath(List<Pair> path) {
        String pathStr = "";

        for (Pair p : path) {
            pathStr = pathStr + p.code + "->";
        }
        pathStr = pathStr.replaceAll("->$", "");

        return pathStr;
    }
}

class Pair {
    public int code;
    public int next;

    public Pair(int code, int next) {
        this.code = code;
        this.next = next;
    }

    @Override
    public int hashCode() {
        return code;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null 
[其他解释]
听起来你应该反向构造这棵树,也就是把 4 当作根节点,然后反向找它的叶子节点,也即:
  3、5、6、8
继续递归找这几子节点的页节点:
  3 -> 1, 2
  5 -> 7
继续递归,直到找不到了,那么你就得到一颗完整的以4为根的树。


这棵树的所有深度遍历路径就是你要的解。
[其他解释]
Dijkstra算法不能解决么?
[其他解释]
可以看看这个文章
http://www.sitepoint.com/hierarchical-data-database-2/
也可以在google查how to store hierarchies in SQL databases

用一个left一个right值描述树的轮廓,每个节点都有一个left和right值,然后查找时通过这两个值可以轻松找到所有parents
[其他解释]
人呢,
有没有精妙的解决方案。。。

热点排行