我有这堂课:
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
存储在值列表中而不是存储在指针列表中?
答案 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
真正代表什么,以及你想要实现的更广泛目标......