非递归后序遍历

发布于 2024-08-05 21:39:57 字数 762 浏览 4 评论 0原文

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

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

I saw the following post order traversal algorithm in some website... it seems to be correct. I just want to verify that this algorithm works correctly — is this algorithm correct for post order traversal without recursion?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

末が日狂欢 2024-08-12 21:39:58

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

关键点是遵守一些基本规则:

- 使用节点选择(例如,在重复循环之前,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);
        }
    }

Try to write iterative versions of pre-order, in-order, and post-order binary traversal methods. You will then see the pattern or methodology of converting their corresponding recursive versions into the iterative versions.

Key point is sticking to some basic rules:

- Use node selection (e.g., currentNode = currentNode->Left before reiterating the loop, etc.) for immediate node traversal.

- Use stack to remember nodes that need to be visited or revisited later.

- If a node need to be "REvisited," detecting / keeping the state so that you can indicate whether the next node needs to be "processed" in next iteration or one of more of the child nodes should be visited before the node can be processed.

If you stick to these rules, you can esily accomplish the tasks.

Here is an example of the iterative post-order traversal. Ignore BinarySearchTree - it works for any binary trees.

    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);
        }
    }
迷鸟归林 2024-08-12 21:39:58

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

no here prev should not start with null
eg:for bst having nodes 5 2 1 3 7 6 8 0
it will not consider zero because at 1 its right is null and this time previous will also be null hence it will not consider its left child i.e. 0
write previous=any value but not null

花之痕靓丽 2024-08-12 21:39:58

这是工作代码

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;

       }
    }

Here is the working code

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;

       }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文