在递归函数中创建std :: list而不是std :: list of pointer

时间:2012-07-04 21:45:57

标签: c++ pointers recursion c++11

我有这堂课:

class obj
{
public:

    obj()
        : parent(nullptr),
        depth(0)
    {   }

    obj* parent;
    list<obj> children;
    int depth;  // Used only for this example
};

为了填充我的数据结构,我使用如下的递归函数:

void recursive(obj& parent)
{
    if(parent.depth == 1)
        return;

    obj son;
    son.parent = &parent;
    son.depth = parent.depth + 1;

    recursive(son);

    parent.children.push_back(son);
}

以这种方式举例:

obj root;
recursive(root);

如果你注意,你可以看到,如果在递归函数中的测试是:

if(parent.depth == n)
    return;
带有n >= 2

这段代码不起作用(“孙子”root->son->son的父级的存储地址 - 依此类推 - 退出递归函数后将不是有效地址)。

解决此问题的一种方法是使用指针列表(list<obj*> children)而不是值列表:

void recursive(obj& parent)
{
    if(parent.depth == 2)
        return;

    obj* son_ptr = new obj();
    son_ptr->parent = &parent;
    son_ptr->depth = parent.depth + 1;

    recursive(*son);

    parent.children.push_back(son_ptr);
}

是否有另一种方法可以执行相同的工作并将obj存储在值列表中而不是存储在指针列表中?

2 个答案:

答案 0 :(得分:4)

在开始创建更多子项之前,是不是只修复了对象的地址?为此,首先将它们放入子列表中,然后递归......

void recursive(obj& parent, int n)
{
    if (parent.depth == n)
        return;

    obj son;
    son.parent = &parent;
    son.depth = parent.depth + 1;
    parent.children.push_back(son);

    recursive(parent.children.back(), n);
}

答案 1 :(得分:1)

您可以考虑在obj中存储唯一ID,以便obj的实例不定义所表示对象的标识,而是定义其ID。如果这样做,您可能会将ID存储到链接相关的obj而不是存储指针。

例如,您可以更改obj课程以包含int字段id

class obj {
public:
    obj()
        : parent(nullptr),
          depth(0)
    {
        // Not thread-safe; would need to get protected if multi-threaded
        id = nextId++;
    }

    static int nextId;

    int id;
    int parentId;
    list<int> childrenIds;

    int depth;  // Used only for this example
};

每当您构造一个新的obj来表示新的逻辑“事物”时,您可以为id字段分配一个新的唯一值。当您想在表示相关“事物”的obj之间建立关系时,您可以 - 例如 - 使用parentId字段而不是parent指针字段:

void recursive(obj& parent)
{
    if (parent.depth == 1) {
        return;
    }

    obj son;
    son.parentId = parent.id;
    son.depth = parent.depth + 1;

    recursive(son);

    parent.childrenIds.push_back(son.id);
}

当您想要关注链接时,这需要更多工作:而不是按照指向父obj的指针,您需要在某些全局{{1}中查找obj你维护的列表(搜索有问题的obj)。

当然,这实际上取决于这些parentId真正代表什么,以及你想要实现的更广泛目标......