遞歸和非遞歸實現 先序、中序、後序遍歷二叉樹


遞歸和非遞歸實現 先序、中序、後序遍歷二叉樹

先序、中序、後序遍歷二叉樹是一個基礎又非常重要的知識點,頻繁出現在《劍指offer》面試題中,很多題目都是二叉樹遍歷的變形。

所以在本文章中,我總結了用遞歸和非遞歸的方法分別實現對二叉樹的先序、中序和後序遍歷。

  • 遞歸實現三種遍歷

    • 先序遍歷

      package algorithm.tree;
      
      /**
       * 
       * @author FHY
       * 遞歸實現
       * 按照先序遍歷樹的順序打印樹結點
       */
      
      /*
       * 樹節點定義
       */
      class TreeNode{
      	int val = 0;
      	TreeNode left;
      	TreeNode right;
      	public TreeNode(int val){
      		this.val = val;
      	}
      }
      
      /* 二叉樹結構如下:
      * 
      *        0
      *      /   \
      *     1     2
      *    / \   / \
      *   3   4 5   6
      *  
      * 先序遍歷結果:0 1 3 4 2 5 6
      */
      
      public class PreOrderTraversal {
          public static void main(String[] args) {			
      		TreeNode root = new TreeNode(0);
      		TreeNode node1 = new TreeNode(1);
      		TreeNode node2 = new TreeNode(2);
      		TreeNode node3 = new TreeNode(3);
      		TreeNode node4 = new TreeNode(4);
      		TreeNode node5 = new TreeNode(5);
      		TreeNode node6 = new TreeNode(6);
      		
      		root.left = node1;
      		root.right = node2;
      		node1.left = node3;
      		node1.right = node4;
      		node2.left = node5;
      		node2.right = node6;
      		printPreOrderTreeNode(root);
      	}
      	
          private static void printPreOrderTreeNode(TreeNode root) {
      		if(root == null)
      			return;
      		System.out.println(root.val);
      		printPreOrderTreeNode(root.left);
      		printPreOrderTreeNode(root.right);
      	}	
      }
      
    • 中序遍歷

      package algorithm.tree;
      
      /**
       * 
       * @author FHY
       * 遞歸實現
       * 按照中序遍歷樹節點的順序打印樹節點
       */
      
      /* 新建二叉樹如下:
      * 
      *        0
      *      /   \
      *     1     2
      *    / \   / \
      *   3   4 5   6
      *   
      * 中序遍歷結果:3 1 4 0 5 2 6
      */	
      public class InOrderTraversal_1 {       
      	public static void main(String[] args) {
      		TreeNode root = new TreeNode(0);
      		TreeNode node1 = new TreeNode(1);
      		TreeNode node2 = new TreeNode(2);
      		TreeNode node3 = new TreeNode(3);
      		TreeNode node4 = new TreeNode(4);
      		TreeNode node5 = new TreeNode(5);
      		TreeNode node6 = new TreeNode(6);
      		
      		root.left = node1;
      		root.right = node2;
      		node1.left = node3;
      		node1.right = node4;
      		node2.left = node5;
      		node2.right = node6;
      		printInOrderTreeNode(root);
      	}
      	
          private static void printInOrderTreeNode(TreeNode root) {
      		if(root.left != null)
      			printInOrderTreeNode(root.left);
      		System.out.println(root.val);
      		if(root.right != null)
      			printInOrderTreeNode(root.right);
      	}     
      }
      
      
    • 後序遍歷

      package algorithm.tree;
      
      /**
       * 
       * @author FHY
       * 遞歸實現
       * 按照後序遍歷樹節點的順序打印樹節點
       */
      
      /* 新建二叉樹如下:
       * 
       *        0
       *      /   \
       *     1     2
       *    / \   / \
       *   3   4 5   6
       *   
       * 後序遍歷結果:3 4 1 5 6 2 0
       */	
      
      public class PostOrderTraversal {
      	public static void main(String[] args) {		
      		TreeNode root = new TreeNode(0);
      		TreeNode node1 = new TreeNode(1);
      		TreeNode node2 = new TreeNode(2);
      		TreeNode node3 = new TreeNode(3);
      		TreeNode node4 = new TreeNode(4);
      		TreeNode node5 = new TreeNode(5);
      		TreeNode node6 = new TreeNode(6);
      		
      		root.left = node1;
      		root.right = node2;
      		node1.left = node3;
      		node1.right = node4;
      		node2.left = node5;
      		node2.right = node6;
      		postOrderTraversal(root);
      	}	
      	
      	private static void postOrderTraversal(TreeNode root) {
      		if(root == null)
      			return;	
      		if(root.left != null)
      			postOrderTraversal(root.left);
      		if(root.right != null)
      			postOrderTraversal(root.right);
      		
      		System.out.println(root.val);	
      	} 	
      }
      
      
  • 非遞歸實現三種遍歷

    • 先序遍歷

      /**
       * Created by FHY on 2019/5/6.
       * 使用非遞歸方法先序遍歷二叉樹。
            1
           / \
          2   3
             /
            4
        以上輸出爲:1->2->3->4
       */
      import java.util.Stack;
      import java.util.ArrayList;
      public class Solution {
          public ArrayList<Integer> preorderTraversal(TreeNode root) {
              ArrayList<Integer> result = new ArrayList<Integer>();
              Stack<TreeNode> stack = new Stack<TreeNode>();           
              if(root == null)
                  return result;  
                            
              stack.push(root);
              TreeNode thisNode = new TreeNode(0);
              
              while(!stack.isEmpty()){
                  thisNode = stack.pop();
                  result.add(thisNode.val);
                  if(thisNode.right != null)
                      stack.push(thisNode.right);
                  if(thisNode.left != null)
                      stack.push(thisNode.left);
              }
              return result;
          }
      }
      
    • 中序遍歷

      package offer1;
      import java.util.Stack;
      
      /**
       * Created by FHY on 2019/5/10.
       * 非遞歸實現樹的中序遍歷
       *        0
       *      /  \
       *     1    2
       *        /   \
       *       3     4
       * 以上樹輸出爲1,0,3,2,4
       */
      public class InOrderTraverse {
          public static void main(String[] args){
              TreeNode root = new TreeNode(0);
              TreeNode node1 = new TreeNode(1);
              TreeNode node2 = new TreeNode(2);
              TreeNode node3 = new TreeNode(3);
              TreeNode node4 = new TreeNode(4);
              root.left = node1;
              root.right = node2;
              node2.left = node3;
              node2.right = node4;
              getInOrderTraverse(root);
          }
      
          public static void getInOrderTraverse(TreeNode root){
              Stack<TreeNode> stack = new Stack<TreeNode>();
              TreeNode p = root;
              TreeNode thisNode = null;
              while(p != null || !stack.isEmpty()){
                  if(p != null){
                      stack.push(p);
                      p = p.left;
                  }else{
                      thisNode = stack.pop();
                      System.out.println(thisNode.val);
                      p = thisNode.right;
                  }
              }
          }
      }
      
    • 後序遍歷

      package offer1;
      
      /**
       * Created by FHY on 2019/5/5.
       * 使用非遞歸方法後序遍歷二叉樹。
            1
           / \
          2   3
             /
            4
         以上樹輸出結果爲:2->4->3->1
       * 要保證根結點在左孩子和右孩子訪問之後才能訪問,因此對於任一結點P,先將其入棧。
       * 如果P不存在左孩子和右孩子,則可以直接訪問它;
       * 或者P存在孩子,但是其孩子都已被訪問過了,則同樣可以直接訪問該結點
       * 若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,左孩子在右孩    子前面被訪問,左孩子和右孩子都在根結點前面被訪問。
       */
      
      import java.util.Stack;
      import java.util.ArrayList;
      
      //樹節點定義
      class TreeNode{
          int val;
          TreeNode left;
          TreeNode right;
          public TreeNode(int val){
              this.val = val;
          }
      }
      
      public class postOrder {
          public static void main(String[] args){
              TreeNode root = new TreeNode(1);
              TreeNode root_left = new TreeNode(2);
              TreeNode root_right = new TreeNode(3);
              root.left = root_left;
              root.right = root_right;
              root_right.left = new TreeNode(4);
              ArrayList result = postorderTraversal(root);
              for(int i = 0; i < result.size(); i++){
                  System.out.println(result.get(i));
              }
          }
          
          public static ArrayList<Integer> postorderTraversal(TreeNode root) {
              ArrayList<Integer> result = new ArrayList<Integer>();
              if(root == null)
                  return result;
              
              Stack<TreeNode> stack = new Stack<TreeNode>();
              stack.push(root);
              TreeNode cur = new TreeNode(0);
              TreeNode pre = null;
              
              while(!stack.isEmpty()){
                  cur = stack.peek();
                  if(cur.left == null && cur.right == null ||
                          (pre != null && (pre == cur.left || pre == cur.right))){
                      result.add(cur.val);
                      pre = cur;
                      stack.pop();
                  }else
                  {
                      if(cur.right != null){
                          stack.push(cur.right);
                      }
                      if(cur.left != null){
                          stack.push(cur.left);
                      }
                  }
              }
              return result;
          }
      }
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章