二叉樹——後序遍歷的遞迴與非遞迴演算法

weixin_34120274發表於2018-04-18

後序遍歷按照“左孩子-右孩子-根結點”的順序進行訪問。

1.遞迴實現

   /**
    * 後序遍歷
    * @param node
    */
   public static void postOrderTraverse(Node node) {
       if (node == null) return;
       postOrderTraverse(node.leftNode);
       postOrderTraverse(node.rightNode);
       System.out.print(node.data + "\t");
   }

2.非遞迴實現

後序遍歷的非遞迴實現是三種遍歷方式中最難的一種。因為在後序遍歷中,要保證左孩子和右孩子都已被訪問並且左孩子在右孩子前訪問才能訪問根結點,這就為流程的控制帶來了難題。

對於任一結點P,將其入棧,然後沿其左子樹一直往下搜尋,直到搜尋到沒有左孩子的結點,此時該結點出現在棧頂,但是此時不能將其出棧並訪問, 因此其右孩子還為被訪問。所以接下來按照相同的規則對其右子樹進行相同的處理,當訪問完其右孩子時,該結點又出現在棧頂,此時可以將其出棧並訪問。這樣就 保證了正確的訪問順序。可以看出,在這個過程中,每個結點都兩次出現在棧頂,只有在第二次出現在棧頂時,才能訪問它。因此需要多設定一個變數標識該結點是 否是第一次出現在棧頂。

   /**
    * 後序遍歷 非遞迴
    * 雙棧法
    * @param root
    */
   public static void postOrder2(Node root) {
       Stack<Node> stack = new Stack<Node>();
       Stack<Node> output = new Stack<Node>();
       Node node = root;
       while (node != null || !stack.isEmpty()) {
           if (node != null) {
               stack.push(node);
               output.push(node);
               node = node.rightNode;
           } else {
               node = stack.pop();
               node = node.leftNode;
           }
       }

       while (output.size() > 0) {
           Node n = output.pop();
           System.out.print(n.data + "\t");
       }
   }

相關文章