繁体   English   中英

在具有重复子树的树上遍历

[英]Traversal on a tree with duplicated subtrees

我在树上有一个简单的递归后序遍历,可以打印所有可能的路径。 问题是需要花费很多时间。

我想使用我的树的属性来节省遍历时间。 属性是我有重复的子树,在下面的例子中,头1的子树出现在树中3次。

          10
  /        |        \
 5         15        1
 /\        / \      / \
2  1      1   6    3   8
  / \    / \
 3   8  3   8

我寻找改进我的遍历,跳过已经通过的子树。 我的想法是存储我已经通过的每个子树,但我无法将其用于后序算法。

感谢帮助。

使用哈希集来存储已访问过的节点,并为您访问的每个节点检查它是否已被访问过:如果没有,请将其添加到访问集,然后照常继续,否则返回。

我不知道你的程序是否允许这种改变....因为我们无法知道在遍历之前是否出现了一个子树,一种可能的方法是重新组织你的树,以便共享重复的子树。

          10
  /        |        \
 5         15        1
 /\        / \      / \
2  1 ------   6    3   8
  / \     
 3   8     

打印所有可能的路径

我认为这是主要问题。 程序的运行时间与要输出的数据量呈线性关系,大致对于程序执行的树中的每一步,它应输出至少一个符号。 所以只要你保持所需的输出相同(即只要你需要输出所有路径),你就没有加速的空间了,你就不能拥有比O(R)更快的算法,其中R是您需要生产的总产量。

事实上,很可能主要的瓶颈是输出本身(控制台或磁盘性能通常比仅仅在内存中行走更糟),所以我认为如果你对程序进行分析,你会发现90%的时间用在输出上。 因此,不仅无法获得更好的渐近解决方案,也无法获得更快的解决方案。 (除非你优化输出本身,但这是一个不同的问题。)

但是,如果您不需要打印所有路径,而是以某种方式处理它们 - 例如,计算它们存在多少,或找到最长路径等 - 那么您的解决方案可以从您重复的事实中获益子树。 实际上,这意味着您没有 ,而是有向无环图 ,这通常允许相当简单的动态编程方法。

假设每个节点代表一个以该节点为根的唯一子树,并且节点值集不是很大,您可以使用它来优化遍历:

string s[MAX_NODE_VALUE + 1];

string post_traverse(Node root)
{
    if(root == NULL)
        return "";
    if(s[root.value].length() == 0)
    {
        s[root.value] += post_traverse(root.left);
        s[root.value] += post_traverse(root.right);
        s[root.value] += itoa(root.value);
        s[root.value] += ' ';
    }
    cout << s[root.value];
    return s[root.value];
}

这只会在你有太多的重复子树和节点值集非常小时才有用,否则会消耗太多空间并花费更多时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM