使用树回溯

时间:2011-07-06 23:56:24

标签: c tree stack backtracking

由于堆栈(使用push和pop),我在树中使用了回溯算法。 它有效,但我有一个问题。堆栈给出的路径是“错误的”。

bool Prefix(Node*root, stack *tas, char *search)
{
    if (!isEmpty(root))
    {
        if (strcmp(search,root->data) != 0)
            push(tas, root->data, search, root);

        if (strcmp(search,root->data) == 0)
        {
            return True ;
        }

        Prefix(root->left, tas, search);
        Prefix(root->right, tas, search);
    }
    return False;
}

例如,我有一棵树:

     Root
    /    \    
   A      B
  / \    / \
 C   D  E   F    

当我想要C的路径时,此函数返回R A B(对于R和A,而不是B,则为ok)。

我不知道它是来自这个函数还是push()函数。 如果你没有在函数中看到任何错误,我会粘贴push(),但它很长。

编辑:我现在好好理解, 我已添加到功能中:
  如果node是叶子,则pop()。 如果我搜索F,它会返回R A B F而不是R B F.我不知道如何避免将A保持在堆栈中。

edit2:

这是代码:(返回R A B F而不是R B F)

bool Prefix(Node*root, stack *tas, char *search)
{
    if (!isEmpty(root))
    {
        if (strcmp(search,root->data) == 0)
            return True ;

        if (LeafOrNot(root) == True ){  //it's a leaf, pop()
            pop(tas);

        if (Prefix(root->left, tas, search))
            return True;
        if (Prefix(root->right, tas, search))
            return True;
    }
    return False;
}

我不明白如何弹出遍历子节点以获得良好的结果,可能是添加 否则为if(前缀(root-> left,tas,search))?有人有想法吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

至少有一个问题是你没有检查调用Prefix的返回值,所以你不知道递归调用是否“完成”(并且你应该停止探索)。 / p>

看到这个的简单方法就是遍历函数调用(给定样本树):

Prefix("Root")
  found "C"?
    no: Prefix("A")
      found "C"?
        no: Prefix("C")
           found "C"?
              yes: return true
        (without check of Prefix("C")): Prefix("D")
           found "C"?
              no: return false
      Prefix("B")
        found "C"?
          no: Prefix("E")
             found "C"?
               no: return false
          Prefix("F")
             found "C"?
               no: return false
       return false
  return false

这表示调用和缩进的顺序粗略地与调用堆栈上的帧相对应。

您可以查看检查Prefix的回复true是否允许您在适当的时间退出。

答案 1 :(得分:2)

我必须同意@Mark Elliot,但乍一看,他的回答似乎令人困惑。您确实需要一个停止条件,因此您不会继续探索其他节点并将它们添加到堆栈中。您正在返回一个bool,以便您可以使用它来测试调用是否找到您要查找的节点。

如果您打算将最后一个节点包含在堆栈中C的路径中,那么您应该在添加到堆栈时删除字符串比较。

例如,你可以这样做。

bool Prefix(Node*root, stack *tas, char *search)
{
    if (!isEmpty(root))
    {
        push(tas, root->data, search, root);

        if (strcmp(search,root->data) == 0)
        {
            return True;
        }

        if (Prefix(root->left, tas, search))
            return True;
        if (Prefix(root->right, tas, search))
            return True;
    }
    return False;
}