У меня только что было это как вопрос для интервью.
И я должен признать, что это одна из самых сложных вещей, которые мне пришлось решать на лету.
Лично я не думаю, что это хороший вопрос, поскольку вы, возможно, знаете трюк (если вы читали Кнут) в этом случае решение становится тривиальным, но вы все равно можете обмануть интервьюера, заставив его / ее думать, что вы решили это на лету.
Это можно сделать, предполагая, что узел хранит дочерние указатели в статическом состоянии.состав.Если узел хранит дочерние указатели в динамической структуре, он не будет работать, так как вам нужно изменить форму дерева на лету (это может работать, но нет гарантии).
Удивительно, но решение - O(n)
(Технически каждый узел посещается ровно дважды без повторного сканирования дерева).
В этом решении используется цикл (поэтому не используется память для стека) и динамически не выделяется memeroy для хранения узлов, которыенужно удалить.Так что это удивительно эффективно.
class Node
{
// Value we do not care about.
int childCount;
Node* children[MAX_CHILDREN];
};
freeTree(Node* root)
{
if (root == NULL)
{ return;
}
Node* bottomLeft = findBottomLeft(root);
while(root != NULL)
{
// We want to use a loop not recursion.
// Thus we need to make the tree into a list.
// So as we hit a node move all children to the bottom left.
for(int loop = 1;loop < root->childCount; ++loop)
{
bottomLeft->children[0] = root->children[loop];
bottomLeft->childCount = std::max(1, bottomLeft->childCount);
bottomLeft = findBottomLeft(bottomLeft);
}
// Now we have a root with a single child
// Now we can delete the node and move to the next node.
Node* bad = root;
root = root->children[0];
delete bad; // Note the delete should no longer destroy the children.
}
}
Node* findBottomLeft(Node* node)
{
while((node->childCount > 0) && node->children[0] != NULL))
{ node = node->children[0];
}
return node;
}
Вышеприведенный метод будет работать до тех пор, пока он всегда является дочерним узлом [0] (даже если он равен NULL).Пока вам не нужно динамически выделять пространство для хранения дочерних элементов [0].В качестве альтернативы просто добавьте еще один указатель на объект узла для хранения списка удаления и используйте его, чтобы превратить дерево в список.