查找可能的替换列表

时间:2012-06-11 19:35:44

标签: algorithm search recursion tree

假设我们有一个二叉树,如下所示:enter image description here

我正在寻找一种算法来找到A的所有等价物。我给出了一个包含该树中元素的数组。规则是,如果节点的所有子节点都存在于数组中,则它等同于在节点中具有节点。 例如,如果我们在数组中有B和C,它相当于有一个A.所以在上面的数组中,F + G = C,C + B = A,所以[B,F,G]也是相当于A.同样[DEFG]也等同于A.

我可以递归调用类似checkSubstitute(node)的东西:

if node in array
return true
else:
    for child in nodeChildren
        if ((child not in array) && (child == terminalNode))
            return false
        else
        return checkSubstitute(child)

这种逻辑有意义吗?另外,我如何使用如上所述的算法存储所有等效数组?

提前致谢!!

2 个答案:

答案 0 :(得分:3)

您提供的方法无法正常工作,因为您始终在for循环的第一次迭代期间返回一个值。 假设你有一个数组[D]。然后checkSubstitute(B)返回True,它应该返回False。

不是使用for循环,而是在两个子节点上进行两次显式调用更容易。这假设每个节点都有零个或两个子节点。如果一个节点可以有一个子节点,则需要进行一些额外的空值检查。

#returns true if Node n exists in NodeList seq, or if its equivalent exists in seq.
function exists(n, seq):
    if n in seq:
        return True
    if not n.hasChildren:
        return False
    return exists(n.leftChild, seq) and exists(n.rightChild, seq)

获得所有等效数组只需要一些组合。

#gets all possible equivalents for the given node. This includes itself.
#An equivalent is a list of nodes, so this method returns a list of lists of nodes.
function getPossibleEquivalents(node):
    ret = new List()
    baseCase = new List()
    baseCase.append(node)
    ret.append(baseCase)
    if not node.hasChildren:
        return ret  
    for each leftEquivalent in getPossibleEquivalents(node.leftChild):
        for each rightEquivalent in getPossibleEquivalents(node.rightChild):
            ret.append(leftEquivalent + rightEquivalent)
    return ret

编辑: 您可以通过嵌套N for循环来为具有0或N个子项的树扩展getPossibleEquivalents:

for each child0Equivalent in getPossibleEquivalents(node.child[0]):
    for each child1Equivalent in getPossibleEquivalents(node.child[1]):
        for each child2Equivalent in getPossibleEquivalents(node.child[2]):
            for each child3Equivalent in getPossibleEquivalents(node.child[3]):
                for each child4Equivalent in getPossibleEquivalents(node.child[4]):
                    ret.append(child0Equivalent + child1Equivalent + child2Equivalent + child3Equivalent + child4Equivalent + child5Equivalent)

如果您想编写一个可以处理包含任意数量子项的树的函数,则需要获取每个子项的每个可能等效项的Cartesian Product。有些语言已经为您实现了笛卡尔积。例如,在python中:

from itertools import product

def getPossibleEquivalents(node):
    ret = [node]
    if len(node.children) == 0: return ret
    for equivalentTuple in product(map(getPossibleEquivalents, node.children)):
        possibleEquivalent = reduce(lambda x,y: x+y, equivalentTuple)
        ret.append(possibleEquivalent)
    return ret

答案 1 :(得分:0)

这个逻辑可以很好地生成所有等效的表示,但是有一些重复,如果你愿意,可以检查和纠正。(我将遵循一些关于复制内容的python约定)

假设你想要[B,C]的所有可能的表示 对于此阵列中的每个节点,您可以将其替换为其子节点,也可以保持原样。因此,递归的一般概念是这样的:

find_equivalent(representation, node){
        // representation is a list which is a valid equivalent representation.
        child = list_of_children_of_node;
        Temp = representation[:]
        for each c in child: Temp.insert(child)


        find_equivalent(representation, next(node,representation))
        N = next(node,Temp)
        Temp.delete(node)
        Li.append(Temp)
        find_equivalent(Temp, N)
        // Here next function takes a list and a node and returns the next element from the list after node.

上面的Li是一个全局的表示数组,你需要在添加时为每个表示调用函数find_equivalent。