Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 高效地遍历单向树_Algorithm_Traversal_Subtree - Fatal编程技术网

Algorithm 高效地遍历单向树

Algorithm 高效地遍历单向树,algorithm,traversal,subtree,Algorithm,Traversal,Subtree,我有一个单向的对象树,其中每个对象都指向它的父对象。给定一个对象,我需要获得它的整个子树的后代,作为对象的集合。这些对象实际上并不在任何数据结构中,但我可以很容易地获得所有对象的集合 天真的方法是检查批处理中的每个对象,查看给定对象是否是祖先,并将其放在一边。这不会太有效率。。。它的开销为O(N*N),其中N是对象的数量 另一种方法是递归方法,这意味着搜索对象的直接子对象,并在下一级重复该过程。不幸的是,这棵树是单向的。。。没有直接接触儿童的方法,这只会比以前的方法稍微便宜一点 我的问题是:这里

我有一个单向的对象树,其中每个对象都指向它的父对象。给定一个对象,我需要获得它的整个子树的后代,作为对象的集合。这些对象实际上并不在任何数据结构中,但我可以很容易地获得所有对象的集合

天真的方法是检查批处理中的每个对象,查看给定对象是否是祖先,并将其放在一边。这不会太有效率。。。它的开销为O(N*N),其中N是对象的数量

另一种方法是递归方法,这意味着搜索对象的直接子对象,并在下一级重复该过程。不幸的是,这棵树是单向的。。。没有直接接触儿童的方法,这只会比以前的方法稍微便宜一点

我的问题是:这里有没有我忽略的高效算法

谢谢


Yuval=8-

您的问题有点抽象,但(向下滚动,可能有点过于特定于mysql)可能是您的选择。读操作的速度非常快,尽管任何修改都非常复杂(平均需要修改一半的树)


不过,这需要修改数据结构的能力。我想如果你能修改结构,你也可以添加对子对象的引用。如果你不能修改结构,我怀疑没有比你的想法更快的了。

数据库的工作方式是一样的,所以做数据库的工作。建立一个哈希表,从父项映射到子项列表。这需要O(n)。然后使用该哈希表将使查找和查询可能更加高效。

在对象指向其直接子对象的位置构建树可能是最好的方法,特别是如果您需要在将来进行查找。建造这棵树在很大程度上取决于原始树的高度。最多需要O(n^2)


在构建树的同时,构建一个哈希表。哈希表将使未来对特定对象的搜索更快(O(1)vs.O(n))。

正如其他人所提到的,构建一个哈希表/对象映射到其(直接)子对象列表

从那里,您可以轻松地查找“目标对象”的直接子对象列表,然后对列表中的每个对象重复该过程

下面是我如何在Java中使用泛型,使用队列而不是任何递归实现的:

public static Set<Node> findDescendants(List<Node> allNodes, Node thisNode) {

    // keep a map of Nodes to a List of that Node's direct children
    Map<Node, List<Node>> map = new HashMap<Node, List<Node>>();

    // populate the map - this is O(n) since we examine each and every node
    // in the list
    for (Node n : allNodes) {

        Node parent = n.getParent();
        if (parent != null) {

            List<Node> children = map.get(parent);
            if (children == null) {
                // instantiate list
                children = new ArrayList<Node>();
                map.put(parent, children);
            }
            children.add(n);
        }
    }


    // now, create a collection of thisNode's children (of all levels)
    Set<Node> allChildren = new HashSet<Node>();

    // keep a "queue" of nodes to look at
    List<Node> nodesToExamine = new ArrayList<Node>();
    nodesToExamine.add(thisNode);

    while (nodesToExamine.isEmpty() == false) {
        // pop a node off the queue
        Node node = nodesToExamine.remove(0);

        List<Node> children = map.get(node);
        if (children != null) {
            for (Node c : children) {
                allChildren.add(c);
                nodesToExamine.add(c);
            }
        }
    }

    return allChildren;
}
公共静态集合findDescents(列出所有节点,节点thisNode){
//将节点映射保留到该节点的直接子节点列表
Map Map=newhashmap();
//填充映射-这是O(n),因为我们检查每个节点
//在名单上
用于(节点n:所有节点){
节点父节点=n.getParent();
如果(父项!=null){
List children=map.get(parent);
if(children==null){
//实例化列表
children=newarraylist();
地图。放置(父、子);
}
添加(n);
}
}
//现在,创建一个thisNode子节点的集合(所有级别)
Set allChildren=newhashset();
//保留要查看的节点“队列”
List nodestoexecast=new ArrayList();
nodesToExamine.add(这个节点);
while(nodestoexecast.isEmpty()==false){
//从队列中弹出一个节点
Node=nodesToExamine.remove(0);
List children=map.get(节点);
如果(子项!=null){
用于(节点c:子节点){
所有儿童。添加(c);
添加(c);
}
}
}
归还所有儿童;
}

如果我记得如何正确计算的话,预期执行时间是O(n)和O(2n)之间的某个值。您一定要查看列表中的每个节点,再加上一些操作以查找节点的所有子节点-在最坏的情况下(如果在根节点上运行该算法),您将查看列表中的每个节点两次。

该算法是返回子节点列表,还是也需要在树中排序?如果节点只指向它们的祖先(即,你不能返回根节点),我看不出你如何才能做到后者。这听起来更像是一个链接列表的集合,而不是一个树型集合:当然,这个算法会导致一个集合。。。我相应地编辑了算法描述=8-)