我有一个类图,对树进行建模。Graph*图表包含指向当前实例(我当前节点)的父级的指针。

class Graph
{
private:

    Graph* parent;
public:
    Graph* getparent();
}

Graph* Graph::getparent()
{
    return this->parent;
}

父级位于nullptr根目录。

我试图从节点开始找到从节点到根的距离。

这是我的尝试:

int Graph::howManyParents(Graph* unparent)
{
    int nbParents(0);
    if(unparent != nullptr)
    {
        nbParents++;
        nbParents =+ howManyParents(this->parent);
    }
    return nbParents;
}

它可以编译但崩溃。调试器向我展示了对该方法的大量调用,但最终出现了 SegFaulting。我的算法有问题吗?


除非您将其传递给根,否则您的递归永远不会停止,因为您总是调用this->howManyParents并因此将其传递给同一个父级,该父级不会变为空。

目前尚不清楚您想要的是距参数的距离还是距 的距离this

查找距给定节点的距离(没有理由使其成为成员):

int howManyParents(Graph* unparent)
{
    int nbParents(0);
    if(unparent != nullptr)
    {
        nbParents = howManyParents(unparent->getparent()) + 1;
    }
    return nbParents;
}

求 距 的距离this

int Graph::howManyParents()
{
    int nbParents(0);
    if(parent != nullptr)
    {
        nbParents = parent->howManyParents() + 1;
    }
    return nbParents;
}

我认为您因递归太深或无限递归而导致堆栈溢出。

检查您的输入是否有错误,以确保它确实是一棵树,因为如果图中出现循环,递归将是无限的。

另外,尝试增加程序的堆栈大小。

在linux上只需运行命令:

ulimit -s unlimited

要在 Microsoft Visual C++ 中执行此操作,只需将此行添加到代码中:

#pragma comment(linker, '/STACK:67108864');

要在 MinGW G++ 中执行此操作,请将此选项添加到编译行:

-Wl,--stack,67108864

但是,我认为非递归解决方案在这里总体上更好。

int Graph::howManyParents(Graph* unparent)
{
    int nbParents(0);
    while (unparent != nullptr)
    {
        nbParents++;
        unparent = unparent->parent;
    }
    return nbParents;
}

最好使用循环而不是递归,这样可以提高性能和代码可读性。

仅在真正需要的地方使用递归。例如,遍历树。


你可以这样做:

int Graph::howManyParents()
{
    return getparent() ? getparent()->howManyParents() + 1 : 0;
}

另外不要忘记编写使您的构造函数parent = nullptr,它不是默认构造函数。


请问您认为“操作员”=+是做什么的?

它是一个赋值运算符和一个一元加运算符:)

第二个问题:方法是类howManyParents的成员吗?Graph(这从类声明中并不明显)

您是否试图找到 与 的距离unparent(正如它是一个参数所表明的那样),或者与 的距离(this正如您的递归所表明的那样)?

啊,你是对的,迭代方法要容易得多。谢谢你,我没有对此感到担忧...我认为我的图表中没有循环。它确实是一棵树,这是肯定的,但是当我使用 BFS 时,我会测试避免已经看到的节点。

您的非递归“解决方案”与原始递归具有相同的错误。