gpt4 book ai didi

c++ - 在迭代 DFS 与递归 DFS 中维护当前节点的上下文

转载 作者:行者123 更新时间:2023-11-28 04:05:54 28 4
gpt4 key购买 nike

我遇到了一个问题,我要在图中寻找一种特殊类型的节点。该算法按以下方式工作:

bool findSpecial(Node n)
{
if(isSpecial(n))
return true;

bool isSpecial = false;
vector<Node> childs = getChildren(n);
foreach(child, childs)
{
isSpecial |= findSpecial(child);
}

if(isSpecial)
markCurrentNodeSpecial(n);

return isSpecial;
}

以上是算法的模板,假设输入是DAG。它在图中寻找特殊节点,如果 DFS 树中的任何节点是特殊节点,则将当前节点标记为特殊节点。

算法基本上是在任何可到达的地方填充这个特殊属性。

然而,在极少数情况下,它可能会导致 Stack Overflow。

我想弄清楚是否可以迭代地完成同样的事情。迭代方法的问题是一个节点的所有子节点是否都被处理的信息并不容易获得。

有什么建议吗?

最佳答案

1) 最简单的解决方案 - std::stack<Node>工作?你应该让它像程序堆栈一样工作 - 推开始 Node在那里,然后弹出一个节点,检查它是否特殊,如果不是 - 推它的 child ,重复。

2) 你不检查你是否已经访问过一个节点 - 也许你可以加快一点速度。 (编辑:我看不懂)

更新:是的,这是一只有趣的野兽。这段代码怎么样?虽然我没有测试它,但主要思想应该可行:将访问分为两个步骤 - 递归之前和之后。

struct StackNodeEntry
{
Node cur;
optional<Node> parent;

enum class Pos
{
before_recursion, after_recursion
} pos;
};

bool findSpecial(Node root)
{
stack<StackNodeEntry> stack;

stack.push({ root, {}, StackNodeEntry::Pos::before_recursion });

while (!stack.empty())
{
auto& e = stack.top();

switch (e.pos)
{
case StackNodeEntry::Pos::before_recursion:
if (isSpecial(e.cur))
{
if (e.parent)
markCurrentNodeSpecial(*e.parent);
stack.pop();
break;
}

for (auto n : getChildren(e.cur))
stack.push({ n, e.cur, StackNodeEntry::Pos::before_recursion });
e.pos = StackNodeEntry::Pos::after_recursion;
break;

case StackNodeEntry::Pos::after_recursion:

if (isSpecial(e.cur))
{
if (e.parent)
markCurrentNodeSpecial(*e.parent);
}
stack.pop(); // don't use e below this line
break;
}
}

return isSpecial(root);
}

关于c++ - 在迭代 DFS 与递归 DFS 中维护当前节点的上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58709244/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com