繁体   English   中英

用散列法解决树同构

[英]Solving Tree Isomorphism with Hashing

给定2棵具有已知根的树,我们如何有效确定树是否同构? 我们只关心树的形状,而不关心节点的值。 如果一棵树可以通过重命名其节点而变成另一棵树,则这些树是同构的。 该算法不需要100%的时间都是正确的,因此只要哈希冲突很少发生,我们就可以使用哈希。

编辑:找到了解决方案,从此帖子中删除了不必要的混乱

经过大量的工作和一些帮助,我想出了一个O(n log n)解决方案,该解决方案在100%的时间内也是正确的。 它基于2个想法:

想法1:树可以表示为列出其子树的字符串。 例如,叶子可以表示为“ L”。 具有2个叶子的树可以表示为“(L),(L)”。 具有包含2个叶子的子树的树可以表示为“(((L),(L)))”等。这种方法的问题是大树将导致长而重复的字符串,这将减慢算法下降。

想法2:可以在哈希图中索引字符串。 我们可以不带一个像“((L),(L))”这样的子字符串,而可以给该字符串分配一个索引号,比方说2。现在我们可以用“ 2”来引用该子树和所有相同的子树,而不必使用字符串表示形式。 字符串是哈希图中的键,值是分配给这些字符串的唯一整数。

这是用于从第一棵树构建哈希图的代码:

我们的第一个电话应该是fill(root, -1, 1)

public static int fill(int current, int previous, int height) {
    ArrayList<Integer> subtrees = new ArrayList<>();
    for (int next : edges[current]) {
        if (next == previous) continue;
        int subtree = fill(next, current, height+1);
        subtrees.add(subtree);
    }
    // We have to sort subtrees for "2,4" and "4,2" to be considered the same
    Collections.sort(subtrees);
    StringBuilder sb = new StringBuilder(height + ".");
    for (Integer subtree : subtrees) {
        sb.append(subtree +",");
    }
    String key = new String(sb);
    if (map.containsKey(key)) return map.get(key);
    int index = map.size(); // assigning next available number
    map.put(key, index);
    return index;
}

现在,我们可以为Tree 2调用fill(用Tree 2信息替换“ edges”,保持HashMap不变)。 如果返回相同的整数,则树匹配。

非常感谢http://logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf

您还可以使用David Matula的“树-整数双射”,将树映射为整数。

这是一种为每棵树分配唯一的自然数的方法。

以下是前32棵树的示例:

1至32的Matula树

有关算法的演练,请参阅本文档中的练习: http : //williamsharkey.com/integer-tree-isomorphism.pdf

暂无
暂无

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

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