1) Самое простое решение - сработает ли std::stack<Node>
? Вы должны заставить его работать так, как работает стек программ - нажмите туда стартовый Node
, затем вставьте узел, проверьте, не является ли он особенным, если нет - нажмите его потомки, повторите.
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);
}