簡體   English   中英

等效子樹

[英]Equivalent subtree

我有兩棵樹。 樹節點定義為

class Node{
  String treeId; 
  String type;       //Each node has type which has fixed value. For example, its color: RED, BLANK, GREEN
  Set<Node> children;
  String ref;        //The ref is a string and allowed value are "0", "1",..."10". The value is null if it is not leaf. 
};

對於葉子,子集為空。

我想知道是否已經完成了一些有效的工作,如何為兩個給定的樹識別等效的子樹。 等效定義為:

1) Both subtree leaves are setsets leaves of original tree. 
2) Both subtrees leaves have same ref value. 
3) for non-leaves node, the equivalent refers to both node have same type and equivalent children. 

謝謝。 如果有一些Java庫可以解決此問題,那就更好了。


輸入應該是兩個樹的根,而輸出是作為等效子樹的根的Node。 樹的高度為100〜,並且有500多個節點。


我現在所做的是為類Node添加了一個新字段。

class Cache{
   Map<String, Set<String>> map = new LinkedHashMap<String, Set<Str>>();
}

映射的鍵是節點ID,而值是該節點ID的此節點可以到達的引用集。 初始化節點時啟動的緩存。

在isEquivalent比較階段,檢查兩個根的引用集之間是否存在重疊。 如果沒有返回false。

我認為這可以幫助減少比較空間的數量。

我不確定1) Both subtree leaves are leaves of original tree. 要求似乎與how to identify equivalent substree for two given tree.相沖突how to identify equivalent substree for two given tree. 否則下面的遞歸方法應該能夠覆蓋其他兩個條件。 可以實現haveSameOriginalTree(r1, r2)方法來滿足我無法理解的第一個條件。 r1r2是需要檢查是否相等的兩個子樹的根。

bool areEquivalent(Node r1, Node r2)
{
    if(r1.children == null && r2.children == null)
    {
        return (haveSameOriginalTree(r1, r2) && (r1.ref == r2.ref));
    }
    if((r1.children == null && r2.children != null) || (r1.children != null && r2.children == null))
    {
        return false;
    }
    // if here then both must be non-leaf nodes
    if(r1.type != r2.type)
    {
        return false;
    }
    if(r1.children.getCount() != r2.children.getCount()) // not sure of correct syntax for Java Sets
    {
        return false;
    }
    for(int i=0; i<r1.children.getCount(); i++)
    {
        if(!areEquivalent(r1.children[i], r2.children[i])) // again please correct the syntax for Sets
        {
            return false;
        }
    }

    return true;
}

讓我知道你的想法。

更新資料

這是上述解決方案的迭代版本。 它使用分配在堆上的堆棧數據結構,而不是推入函數的調用堆棧,因此與遞歸沒有太大區別,但仍然更好。 另外,由於我們僅保留對Node的引用(而不是復制整個對象),因此如果我們已經將原始樹加載到內存中,那么這不應該是那么多的額外內存開銷。

bool areEquivalent(Node r1, Node r2)
{
    Stack<Node> s1 = new Stack<Node>();
    Stack<Node> s2 = new Stack<Node>();
    Node n1, n2;

    s1.Push(r1);
    s2.Push(r2);
    while(true) // Need a better check
    {
        if(s1.getCount() != s2.getCount())
        {
            return false;
        }
        if(s1.getCount() == 0) // if both stacks are empty then we've traversed both trees without failure.
        {
            return true;
        }
        n1 = s1.Pop();
        n2 = s2.Pop();
        if(!areEquivalentNodes(n1, n2))
        {
            return false;
        }
        foreach(Node child in n1.children)
        {
            s1.Push(child);
        }
        foreach(Node child in n2.children)
        {
            s2.Push(child);
        }
    }
}

// only checks the two nodes are equivalent. their childrens' equivalence will be handled by other calls to this method.
bool areEquivalentNodes(Node n1, Node n2)
{
    if(n1.children.getCount() != n2.children.getCount())
    {
        return false;
    }
    if(n1.children.getCount() == 0) // if both are leaf nodes...
    {
        if(n1.ref != n2.ref)
        {
            return false;
        }
    }
    else // both are non-leaf
    {
        if(n1.type != n2.type)
        {
            return false;
        }
        // the condition that children of non-leaf nodes be equivalent will be covered by subsequent calls this method...
    }

    return true;
}

請注意,這兩個解決方案,希望children在同一順序兩個等價節點。 如果未訂購children則在調用上述代碼之前,我們需要對它們進行排序。

讓我知道這是否更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM