Essayez d'écrire des versions itératives des méthodes de traversée binaire précommande, en ordre et après commande. Vous verrez alors le modèle ou la méthodologie de conversion de leurs versions récursives correspondantes dans les versions itératives.
Point clé colle à quelques règles de base:
- Sélection de nœud Utilisation (par exemple, currentNode = currentNode-> gauche avant de réitérer la boucle, etc.) pour traversal noeud immédiat.
- Utilisez la pile pour mémoriser les nœuds qui doivent être visités ou revisités plus tard.
- Si un noeud doit être "REvisited", détecter/conserver l'état afin de pouvoir indiquer si le noeud suivant doit être "traité" lors de la prochaine itération ou si l'un des autres noeuds enfant doit être visité avant le le noeud peut être traité.
Si vous respectez ces règles, vous pouvez facilement accomplir les tâches.
Voici un exemple de la traversée itérative d'un ordre après l'ordre. Ignorer BinarySearchTree - cela fonctionne pour tous les arbres binaires.
public static IEnumerator<BinarySearchTreeNode<T>> GetPostOrderTraverseEnumerator(BinarySearchTreeNode<T> root)
{
if (root == null)
{
throw new ArgumentNullException("root");
}
Stack<BinarySearchTreeNode<T>> stack = new Stack<BinarySearchTreeNode<T>>();
BinarySearchTreeNode<T> currentNode = root;
// If the following flag is false, we need to visit the child nodes first
// before we process the node.
bool processNode = false;
while (true)
{
// See if we need to visit child nodes first
if (processNode != true)
{
if (currentNode.Left != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
if (currentNode.Right != null)
{
// Remember to visit the right child node later
stack.Push(currentNode.Right);
}
// Visit the left child
currentNode = currentNode.Left;
continue;
}
else if (currentNode.Right != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
// Visit the right child
currentNode = currentNode.Right;
continue;
}
}
// Process current node
yield return currentNode;
// See if we are done.
if (stack.Count == 0)
{
break;
}
// Get next node to visit from the stack
BinarySearchTreeNode<T> previousNode = currentNode;
currentNode = stack.Pop();
// See if the next node should be processed or not
// This can be determined by the fact that either of the current node's child nodes
// has just been processed now.
processNode = (previousNode == currentNode.Left || previousNode == currentNode.Right);
}
}
Avez-vous lu le reste du fil à Algogeeks? http://www.mail-archive.com/[email protected]/msg03546.html – APC
Ce n'est pas * syntaxiquement * récursif car c'est * émulant * récursivité avec PUSH et POP. – RBarryYoung
Barry, je dirais qu'il n'est même pas nécessaire de le qualifier d '"émulant". –