簡體   English   中英

使用一個堆棧的后序遍歷

[英]PostOrder Traversal using one stack

我正在嘗試了解使用堆棧的 DFS 樹遍歷。 我發現將遞歸解決方案轉換為迭代解決方案以進行預序遍歷非常直觀。 但是,我發現使用此鏈接很難理解后序遍歷。 https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/ 是否有一種直觀且更簡單的思考方式? 預購代碼:

void iterativePreorder(node *root)
{
    // Base Case
    if (root == NULL)
       return;

    // Create an empty stack and push root to it
    stack<node *> nodeStack;
    nodeStack.push(root);

    /* Pop all items one by one. Do following for every popped item
       a) print it
       b) push its right child
       c) push its left child
    Note that right child is pushed first so that left is processed first */
    while (nodeStack.empty() == false)
    {
        // Pop the top item from stack and print it
        struct node *node = nodeStack.top();
        printf ("%d ", node->data);
        nodeStack.pop();

        // Push right and left children of the popped node to stack
        if (node->right)
            nodeStack.push(node->right);
        if (node->left)
            nodeStack.push(node->left);
    }
}

使用前序遍歷,代碼

  • 顯示當前節點的數據
  • 遍歷左子樹
  • 遍歷右子樹

使用后序遍歷,代碼

  • 遍歷左子樹
  • 遍歷右子樹
  • 顯示當前節點的數據

所以不同的是在進行后序遍歷時需要將數據存入棧中,以便最后打印。 有幾種不同的方法可以實現這一點。 一種方法是更改​​堆棧實現以區分子指針和數據指針。

當一個子指針被彈出時,動作是

  • 將當前節點作為數據指針推送
  • 將右節點作為子指針推送
  • 將左節點作為子指針推送

當一個數據指針被彈出時,動作是

  • 顯示節點的數據

然后通過將根節點作為子指針推送來開始遍歷。

雖然代碼更難,但迭代后序比其他遍歷更直觀,因為其他遍歷已經重構,而這個不能類似地重構。

在這里使用第一個解決方案:https ://articles.leetcode.com/binary-tree-post-order-traversal/

直覺是遞歸函數具有迭代方法沒有的信息,主要是遍歷的方向。 當遞歸函數執行或反沖時,它知道它從哪里來,它是從哪一行代碼執行的。 IE 如果您正在打印或處理當前節點,您就知道您已經訪問了子節點,因為它們已經被遞歸調用了。

迭代解決方案可以通過使用“前一個”指針來跟蹤它,因此您會看到“如果前一個不是當前節點的任何一個子節點”的檢查,那么這意味着您正在向下遍歷並且需要向左移動。 其他可能性是前一個來自左子節點或右子節點。 處理完所有案例后,您就有了解決方案。

請在下面使用 Java 中的一個堆棧找到 PostOrder Traversal 的代碼片段

public class PostOrderWithoutRecurssion {

    static Stack<Node> stack = new Stack<Node>();

    static class Node{
        int data;
        int status;
        Node left, right;

        Node(int data){
            this.data = data;
            this.status=0;
        }
    }//end class Node

    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.left.left = new Node(8);
        root.left.left.right = new Node(9);

        postOrderWithoutRecurssion(root);
    }//end main

    public static void postOrderWithoutRecurssion(Node root) {
        Node temp = root;

        while(temp!=null || stack.size()>0) {

            while(temp!=null) {
                temp.status = 1;
                stack.push(temp);
                temp = temp.left;
            }

            temp = stack.pop();

            if(null==temp.left && null == temp.right) {
                temp.status = 2;
                System.out.println(temp.data);
            }else if(null != temp.right) {
                if(temp.left.status==2 && temp.right.status==2) {
                    temp.status = 2;
                    System.out.println(temp.data);
                    temp = null;
                }else {
                    if(temp.status!=1) {
                        temp.status = 1;
                        stack.push(temp);
                    }else {
                        stack.push(temp);
                    }
                }
            }

            if(null!=temp) {
                temp = temp.right;    
            }

        }
    }//end postOrderWithoutRecurssion
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM