Одним из способов реализации DFS является использование рекурсивной функции, такой как следующее
void depth_first_search(const nodeptr_t node)
{
// Do something with node
// ...
if (node->left)
depth_first_search(node->left);
if (node->right)
depth_first_search(node->right);
}
. Вы можете легко заставить эту функцию узнать, на какой глубине она находится, следующим образом
void depth_first_search(const nodeptr_t node, unsigned depth)
{
// Do something with node and depth
// ...
if (node->left)
depth_first_search(node->left, depth + 1);
if (node->right)
depth_first_search(node->right, depth + 1);
}
В этом случае «сделать что-то» будет обновлять некоторый контейнер (например, std::vector
) с помощью счетчиков типов узлов, с которыми он столкнулся на этой глубине.Для этого вам, конечно, нужно, чтобы эта структура была доступна изнутри функции.Это может быть достигнуто либо
- Делая контейнер (или указатель, либо ссылку на него) глобальной переменной
- Реализуя
depth_first_search
в классе, в котором контейнер является членом - Передача контейнера в качестве дополнительного аргумента
depth_first_search
Вариант этого последнего варианта - использовать «Шаблон посетителя», например,
void depth_first_search(const nodeptr_t node, unsigned depth, Visitor& visitor)
{
// Do something with node and depth
// ...
visitor.visit(node, depth);
if (node->left)
depth_first_search(node->left, depth + 1, visitor);
if (node->right)
depth_first_search(node->right, depth + 1, visitor);
}
Некоторые классы, производные от Visitor
, теперь точно знают, что делать с информацией об узле и глубине (например, подсчитать их и сохранить результаты в контейнере).Преимущество здесь в том, что если вам нужно сделать что-то другое с вашими узлами в следующий раз, вы просто реализуете нового посетителя.