非递归的邮政订单遍历

时间:2009-09-24 12:08:35

标签: c# algorithm data-structures iteration

我在某些网站上看到了以下邮政订单遍历算法......似乎是正确的。我只是想验证这个算法是否正常工作 - 这个算法对于没有递归的后序遍历是否正确?

void postOrderTraversal(Tree *root)
{
    node * previous = null;
    node * s = null;
    push(root);
    while( stack is not empty )
    {
        s = pop();

        if(s->right == null and s->left == null)
        {
            previous = s;
            process s;
        }
        else
        {
            if(s->right == previous or s->left == previous)
            {
                previous = s;
                process s;
            }
            else
            {
                push( s );
                if(s->right) { push(s->right); }
                if(s->left)  { push(s->left);  }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:2)

尝试编写预订,有序和后序二进制遍历方法的迭代版本。然后,您将看到将相应的递归版本转换为迭代版本的模式或方法。

关键点是坚持一些基本规则:
   - 使用节点选择(例如,currentNode = currentNode->重复循环之前的Left等)进行立即节点遍历。
   - 使用堆栈记住以后需要访问或重新访问的节点。
   - 如果节点需要“重新访问”,则检测/保持状态,以便您可以指示下一个节点是否需要在下一次迭代中“处理”,或者在节点可以访问之前应该访问一个或多个子节点处理。

如果您遵守这些规则,您可以轻松完成任务。

以下是迭代后序遍历的示例。忽略BinarySearchTree - 它适用于任何二叉树。

    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);
        }
    }

答案 1 :(得分:1)

不,这里不应该以null开头 例如:对于具有节点5 2 1 3 7 6 8 0的bst 它不会考虑零,因为在1处它的右边是空的,这次前面也将是null因此它不会考虑它的左边的孩子,即0 写previous =任何值但不为null

答案 2 :(得分:1)

这是工作代码

Stack s=new Stack();
    while(true){
       if(root!=null){
           s.push(root);
           root=root.left;
       }
       else{
            if(s.top().right==NULL){
               root=s.top();
               s.pop();
               System.out.println(root.data);
               if(root==s.top().right){
                    System.out.println(s.top().data);
                    s.pop();
               }
            }
       if(!s.empty())
          root=s.top().right;
       else 
          root=NULL;

       }
    }