Java 如何从平面树结构中查找所有子体

Java 如何从平面树结构中查找所有子体,java,algorithm,tree,Java,Algorithm,Tree,我有一个表示层次关系的平面数据,如下所示: ID名称PID 0表示空值 1 B 0 2c0 4d1 5 E 1 6 F 4 3g0 此表表示“数据表”,其中PID表示父元素。 例如,在第一行中,我们看到A有PID null,而B有PID 0,这意味着B的父元素是A,因为0是A的ID,A是根元素,因为它没有PID。类似地,C有父A,因为C也有PID 0,0是A的ID 我创建了一个类RecordHolder来表示上表。我还实现了方法processRecordHolder 公共映射进程RecordH

我有一个表示层次关系的平面数据,如下所示:

ID名称PID
0表示空值
1 B 0
2c0
4d1
5 E 1
6 F 4
3g0
此表表示“数据表”,其中PID表示父元素。 例如,在第一行中,我们看到A有PID null,而B有PID 0,这意味着B的父元素是A,因为0是A的ID,A是根元素,因为它没有PID。类似地,C有父A,因为C也有PID 0,0是A的ID

我创建了一个类
RecordHolder
来表示上表。我还实现了方法
processRecordHolder

公共映射进程RecordHolder()
返回的映射使用元素作为键,并将子节点集合作为值保存。例如,映射中的第一项对应于元素A,它有许多子元素,而元素C没有子元素。输出中成员的顺序并不重要

publicstaticvoidmain(字符串[]args){
RecordHolder dt=新的RecordHolder();
dt.addRow(0,“A”,空);
dt.addRow(1,“B”,0);
dt.addRow(2,“C”,0);
dt.addRow(4,“D”,1);
dt.addRow(5,“E”,1);
dt.addRow(6,“F”,4);
dt.addRow(3,“G”,0);
System.out.println(“输出:”);
System.out.println(dt.processRecordHolder());
}
输出:
{D=[F],A=[B,C,G,D,E,F],B=[D,E,F]}
或
{D=[F],E=null,F=null,G=null,A=[B,C,G,D,E,F],B=[D,E,F],C=null}
以下是我迄今为止能够实现的
记录

公共类记录{
公共整数id;
公共字符串名称;
公共整数父ID;
公开记录家长;
公众收集儿童;
公共记录(整数id、字符串名称、整数parentId){
这个();
this.id=id;
this.name=名称;
this.parentId=parentId;
}
公共记录(){
children=Collections.newSetFromMap(新的ConcurrentHashMap())
}
公共集合getChildren(){
返回儿童;
}
公共记录getParent(){
返回父母;
}
公共整数getParentId(){
返回parentId;
}
@凌驾
公共字符串toString(){
返回“记录{“+”id=“+id+”,name=“+name+”,parentId=“+parentId+”}”;
}
/*(非Javadoc)
*@see java.lang.Object#hashCode()
*/
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((id==null)?0:id.hashCode();
result=prime*result+((name==null)?0:name.hashCode();
result=prime*result+((parentId==null)?0:parentId.hashCode();
返回结果;
}
/*(非Javadoc)
*@see java.lang.Object#equals(java.lang.Object)
*/
@凌驾
公共布尔等于(对象obj){
if(this==obj){
返回true;
}
if(obj==null){
返回false;
}
如果(!(obj记录实例)){
返回false;
}
记录其他=(记录)obj;
if(id==null){
if(other.id!=null){
返回false;
}
}如果(!id.equals(other.id)){
返回false;
}
if(name==null){
if(other.name!=null){
返回false;
}
}如果(!name.equals(other.name)){
返回false;
}
if(parentId==null){
if(other.parentId!=null){
返回false;
}
}如果(!parentId.equals(other.parentId)){
返回false;
}
返回true;
}    
}

现在我无法理解其他步骤,我应该怎么做?

以防您想尝试我的更简单的实现想法,这里是简要的细节。通过这种方式,你可以决定是使用你目前的想法,还是尝试重新使用这个想法。(注意,下面的代码是作为伪Java大纲提供的,它不会编译,也不会测试):

然后是一个节点类:

class Node{
    char value;
    Node parent;
    public Node(value, parentID){
        this.value = value;
        if(parentID == -1)
            parent = null;
        else
            parent = nodes[parentID]; //nodes will have to be a global array or get passed to the constructor
    }
}
请注意,只有在节点[parentID]中的项之前已初始化的情况下,此构造函数才会工作。(当前输入文件顺序是这样,但在其他情况下可能不这样。)

祖先: 要使用此方法使用ID查找节点的祖先,只需执行以下操作:

printAncestry(nodes[ID]);

void printAncestry(Node n){
    System.out.println("Child: " + n.value);
    System.out.println("Ancestry: ");
    while(n.parent != null){
        n = n.parent;
        System.out.println(n.value);
    }
}
尝试:

公共类记录持有者{
Map namesById=new HashMap();
Map childrenById=new HashMap();
public void addRow(整数id、字符串名称、整数父级){
namesById.put(id,name);
List children=childrenById.get(parent);
if(children==null){
children=newarraylist();
childrenById.put(父,子);
}
儿童。添加(id);
}
公共映射processRecordHolder(){
映射结果=新的HashMap();
子代(null,results);
返回结果;
}
私有列表子体(整数id、映射结果){
final List childrenNames=new ArrayList();
最终列表childrenIds=childrenById.get(id);
if(childrenIds!=null&&childrenIds.size()>0){
for(整数childrenId:childrenId){
最后一个字符串childName=namesById.get(childrenId);
childrenNames.add(childName);
最终列表孙子姓名=后代(childrenId,results);
儿童姓名。addAll(孙子姓名);
}
如果(id!=null){
results.put(namesById.get(id),childrenNames);
}
}
返回儿童姓名;
}
}

这似乎非常复杂。我直观的方法是使用ID作为索引创建一个数组,并创建类似linkedlist的节点作为数组中的值。(基本上,使用每个节点中的引用字段引用子节点,使用数组保存所有节点。)
printAncestry(nodes[ID]);

void printAncestry(Node n){
    System.out.println("Child: " + n.value);
    System.out.println("Ancestry: ");
    while(n.parent != null){
        n = n.parent;
        System.out.println(n.value);
    }
}
public class RecordHolder {

    Map<Integer,String> namesById = new HashMap<>();
    Map<Integer,List<Integer>> childrenById = new HashMap<>();

    public void addRow(Integer id, String name, Integer parent) {
        namesById.put(id, name);
        List<Integer> children = childrenById.get(parent);
        if (children == null) {
            children = new ArrayList<>();
            childrenById.put(parent, children);
        }
        children.add(id);
    }

    public Map<String,List<String>> processRecordHolder() {
        Map<String,List<String>> results = new HashMap<>();
        descendants(null, results);
        return results;
    }

    private List<String> descendants(Integer id, Map<String, List<String>> results) {
        final List<String> childrenNames = new ArrayList<>();

        final List<Integer> childrenIds = childrenById.get(id);
        if (childrenIds != null && childrenIds.size() > 0) {
            for (Integer childrenId : childrenIds) {

                final String childName = namesById.get(childrenId);
                childrenNames.add(childName);

                final List<String> grandchildrenNames = descendants(childrenId, results);
                childrenNames.addAll(grandchildrenNames);
            }

            if (id != null) {
                results.put(namesById.get(id), childrenNames);
            }
        }

        return childrenNames;
    }
}