二叉樹遍歷總結和重構

BinaryTree的各種操作,包括求高度、三種深度優先遍歷方式(前序、中序、後續的遞歸和非遞歸)、層次遍歷(寬度優先遍歷)
Leetcode題目:
*1、144 先序遍歷二叉樹
* 2、 94 中序遍歷二叉樹
* 3、145 後序遍歷二叉樹
* 4、102 107 層次遍歷二叉樹
* 5、105 先序序列和中序序列重構二叉樹
* 6、106 後序序列和中序序列重構二叉樹**

import java.util.*;
/**
* BinaryTree的節點定義
*
*/
class TreeNode {
     int val;
     TreeNode left, right;

     public TreeNode(int val) {
          this.val = val;
     }
}

/**
*
*/
public class BinaryTree {
     private TreeNode root;

     public BinaryTree(TreeNode root) {
          this.root = root;
     }


     /**
     * leetcode NO.144
     * 先序遍歷樹,遞歸版本
     *
     * @param root
     */
     public List<Integer> preorderTraversal(TreeNode root) {
          List<Integer> list = new ArrayList<Integer>();
          if (root != null) {
               // visit(root);
               list.add(root.val);
               list.addAll(preorderTraversal(root.left));
               list.addAll(preorderTraversal(root.right));
          }
          return list;
     }
     /**
     * 先序遍歷樹,迭代版本
     *
     * @param root
     * @return
     */
     public List<Integer> preorderTraversalIterative(TreeNode root) {
          List<Integer> list=new ArrayList<Integer>();
          Stack<TreeNode> stack=new Stack<TreeNode>();
          TreeNode visit=root;
          while(visit!=null || !stack.isEmpty()){
               if(visit!=null){                           //依次遍歷並訪問所有的左節點,直到左節點爲空,
                    list.add(visit.val);
                    stack.push(visit);                    //將遍歷的每一個節點存儲到棧中
                    visit=visit.left;
               }else{                                   //遍歷棧訂節點的右節點
                    visit=stack.pop();
                    visit=visit.right;
               }              
          }
          return list;
     }
     /**
     * leetcode NO.94
     * 中序遍歷樹,遞歸版本
     * @param root
     * @return
     */
     public List<Integer> inorderTraversal(TreeNode root){
          List<Integer> list=new ArrayList<Integer>();
          if(root!=null){
               list.addAll(inorderTraversal(root.left));
               list.add(root.val);
               list.addAll(inorderTraversal(root.right));
          }
          return list;
     }
     /**
     * 中序遍歷樹,迭代版本;
     * @param root
     * @return
     */
     public List<Integer> inorderTraversalIterative(TreeNode root){
          List<Integer> list=new ArrayList<Integer>();
          Stack<TreeNode> stack=new Stack<TreeNode>();
          TreeNode visit=root;
          while(visit!=null || !stack.isEmpty()){
               if(visit!=null){          //先遍歷所有左節點,將左節點加入棧中,直到左節點爲空
                    stack.push(visit);      
                    visit=visit.left;
               }else{                         //訪問棧頂元素,並遍歷棧頂元素的右節點
                    visit=stack.pop();
                    list.add(visit.val); //與前序遍歷的區別是該節點訪問的位置,先入棧再訪問
                    visit=visit.right;
               }
          }
          return list;
     }

     /**
     * leetcode NO.145
     * 後續遍歷樹,遞歸版本
     * @param root
     * @return
     */
     public List<Integer> postorderTraversal(TreeNode root){
          List<Integer> list=new ArrayList<Integer>();
          if(root!=null){
               list.addAll(postorderTraversal(root.left));
               list.addAll(postorderTraversal(root.right));    
               list.add(root.val);
          }
          return list;
     }
     /**
     *
     * 後續遍歷樹,迭代版本
     * 後續遍歷的順序是left->right->root,前序遍歷的順序是root->left->right
     * 將前序遍歷順序調整成root->right->left,然後倒序輸出,即爲後序遍歷的順序。
     * @param root
     * @return
     */
     public List<Integer> postorderTraversalIterative(TreeNode root){
          LinkedList<Integer> list=new LinkedList<Integer>();
          Stack<TreeNode> stack=new Stack<TreeNode>();
          TreeNode visit=root;
          while(visit!=null || !stack.isEmpty()){
               if(visit!=null){
                    list.addFirst(visit.val);   //將每一個數據在頭部添加,相當於倒序的效果
                    stack.push(visit);
                    visit=visit.right;
               }else {
                    visit=stack.pop();
                    visit=visit.left;
               }
          }
          return list;
     }
     /**
     * leetcode NO.102
     * 層次遍歷,按層次信息添加到二維列表中
     * [ [3],[9,20],[15,7]]
     * 思路:用兩個隊列存儲當前層的節點和下一層的節點,直到當前層節點個數爲0
     * @param root
     * @return
     */
     public List<List<Integer>> levelOrder(TreeNode root) {
          List<List<Integer>> list=new LinkedList<List<Integer>>();
        List<TreeNode> currentQueue=new LinkedList<TreeNode>();  //當前層的節點隊列
        if(root==null) return list;
        currentQueue.add(root);
        while(currentQueue.size()!=0){
             List<Integer> currentList=new LinkedList<Integer>();  //當前層節點的值
             List<TreeNode> nextQueue=new LinkedList<TreeNode>();     //下一層的節點隊列
             for(TreeNode node:currentQueue){
                  currentList.add(node.val);
                  if(node.left!=null) nextQueue.add(node.left);
                  if(node.right!=null) nextQueue.add(node.right);
             }
             list.add(currentList);
             currentQueue=nextQueue;
        }
        return list;
    }
     /**
     * leetcode NO.107
     * For example:
     Given binary tree {3,9,20,#,#,15,7},
    3
   / \
  9  20
    /  \
   15   7
     return its bottom-up level order traversal as:
[
  [15,7],
  [9,20],
  [3]
]
     * @param root
     * @return
     */
     public List<List<Integer>> levelOrderBottom(TreeNode root) {
          LinkedList<List<Integer>> list=new LinkedList<List<Integer>>();
        List<TreeNode> currentQueue=new LinkedList<TreeNode>();  //當前層的節點隊列
        if(root==null) return list;
        currentQueue.add(root);
        while(currentQueue.size()!=0){
             List<Integer> currentList=new LinkedList<Integer>();  //當前層節點的值
             List<TreeNode> nextQueue=new LinkedList<TreeNode>();     //下一層的節點隊列
             for(TreeNode node:currentQueue){
                  currentList.add(node.val);
                  if(node.left!=null) nextQueue.add(node.left);
                  if(node.right!=null) nextQueue.add(node.right);
             }
             list.addFirst(currentList); //與levelOrder()的區別僅在於此,每次在鏈表頭部添加,避免了倒序過程
             currentQueue=nextQueue;
        }
        return list;
    }

     /**
     * 5、105 先序序列和中序序列重構二叉樹
     * @param preorder
     * @param inorder
     * @return
     */
     public TreeNode buildTreePreIn(int[] preorder, int[] inorder) {
        if(preorder.length!=inorder.length ||  preorder.length==0 || inorder.length==0 )
             return null;
        return buildTreeProcessor(preorder,0,inorder,0,preorder.length);
    }
     /**
     *
     * @param preorder 先序遍歷序列數組
     * @param prestart 先序遍歷序列開始下標
     * @param inorder  中序遍歷序列數組
     * @param instart     中序遍歷序列開始下標
     * @param len          序列長度
     * @return
     */
     public TreeNode buildTreeProcessor
     (int[] preorder,int prestart,int[] inorder,int instart,int len){
          if(prestart>preorder.length) return null;
          TreeNode root=new TreeNode(preorder[prestart]);
          int i=0;
          while(i<len){          //找到根節點在中序遍歷序列中的位置
               if(preorder[prestart]!=inorder[i+instart]){
                    i++;
               }else break;
          }
          if(i>0){          //如果左子樹存在,遞歸構建左子樹
               root.left=buildTreeProcessor(preorder, prestart+1,inorder,instart,i);
          }
          if(i<len-1){     //如果右子樹存在,遞歸構建右子樹
               root.right=buildTreeProcessor(preorder,prestart+1+i,inorder,instart+i+1,len-i-1);
          }

          return root;
     }


     /**
     * 6、106 後序序列和中序序列重構二叉樹
     */

     public static TreeNode buildTreePostIn(int[] inorder, int[] postorder) {
        if(inorder.length!=postorder.length || inorder.length==0 || postorder.length==0)
             return null;
        return buildTreePostInProcessor(inorder,inorder.length-1,postorder,postorder.length-1,inorder.length);
    }
     /**
     *
     * @param inorder
     * @param instart
     * @param postorder 後序遍歷序列
     * @param postend  後序遍歷序列尾部下標
     * @param len
     * @return
     */
     public static TreeNode buildTreePostInProcessor
     (int[] inorder,int inend,int[] postorder,int postend,int len){
          if(postend<0) return null;
          TreeNode root=new TreeNode(postorder[postend]);
          int i=0;
          //找出中序序列中根節點的位置下標,此處從後往前計數(中序和後序都從後往前遍歷)
          /*while(i<len ){   
               if(inorder[i+instart]!=postorder[postend]){
                    i++;
               }else break;
          }*/
          while(inend-i>=0){
               if(inorder[inend-i]!=postorder[postend]){
                    i++;
               }else break;
          }
          if(i<len-1) root.left=buildTreePostInProcessor(inorder,inend-i-1,postorder,postend-i-1,len-i-1);
          if(i>0) root.right=buildTreePostInProcessor(inorder,inend,postorder,postend-1,i);
          return root;
     }

     public static void main(String [] args){
          int[] inorder={1,2,3,4};
          int[] postorder={1,3,4,2};
          buildTreePostIn(inorder,postorder);
     }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章