LeetCode 94/144/145: Binary Tree Inorder/Preorder/Postorder Traversal LeetCode

怎甘沉沦 提交于 2020-01-29 01:16:49

LeetCode 94 Inorder 问题描述

在这里插入图片描述

思路

中序遍历: 按照 左结点 根节点 右结点的顺序
递归实现 : preorder方法实现按照 左结点 根节点 右结点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由inorder方法实现。
非递归实现 :通过一个栈,从根节点开始入栈,如果当前结点不为空或者栈不为空,进入循环,只要一直存在左节点就一直入栈,不存在左节点就出栈访问当前结点,当前结点设置为出栈节点的右节点, 然后继续循环遍历

在这里插入图片描述

java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

// //way1递归
// class Solution {
//         List<Integer> result=new ArrayList<Integer>();
//         public List<Integer> inorderTraversal(TreeNode root) {
//             inorder(root);
//             return result;

//         }
//         private  void inorder(TreeNode node){
//             if(node==null)
//                 return;
//             if(node.left!=null)
//                 inorder(node.left);//左
//             result.add(node.val);//根
//             if(node.right!=null)
//                 inorder(node.right);//右

//         }
// }

// way2 非递归方式
// 通过一个栈,从根节点开始入栈,只要一直存在左节点就一直入栈,不存在左节点就出栈访问节点值,然后继续遍历出栈那个节点的右节点
public class Solution {
        public List < Integer > inorderTraversal(TreeNode root) {
            List < Integer > result = new ArrayList < > ();
            Stack < TreeNode > stack = new Stack < > ();
            TreeNode current = root;
            while (current!=null || !stack.isEmpty()){
            //一直找到最左边的结点
                while (current!=null) {
                    stack.push(current);
                    current = current.left;
                }
            current=stack.pop();
            result.add(current.val);
            current=current.right;
            }
            return result;
        }
}

LeetCode 144 Preorder问题描述

在这里插入图片描述

思路

前序遍历: 按照 根节点 左结点 右结点的顺序
递归实现1 (遍历法): preorder方法实现按照 根节点 左结点 右结点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由preorder方法实现。
递归实现2(分治法) :按照 根节点 整个左子树 真个右子树的顺序加入,将这个分为左右两部分,最后合并。(中序和后续遍历也可以这样实现,本文中没有写)

  • 两种方式的共同之处:都是递归实现
  • 两种方式的区别:
    (1)第一种方法存放结果的是一个全局变量,只有这一个结果容器存放结果。
    第二种方式:每次都新建立一个容器,相当于局部的解,是有意义的,最后将所有容器的结果合并到结果容器
    (2)参数和返回值不同
    (遍历法是从上到下,分治法是从下往上)

非递归实现 :通过一个栈,从根节点开始入栈,如果栈不为空,进入循环,出栈访问当前结点,若当前结点的右结点不为空,右结点入栈,若当前结点的左结点不为空,左结点入栈,然后进入下一次循环(因为栈是先进后出 所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点)

在这里插入图片描述

java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
//    // way1 递归方式1
//    class Solution {
//        List<Integer> result=new ArrayList<Integer>();
//        public List<Integer> preorderTraversal(TreeNode root) {
//            //4.递归的调用
//            preorder(root);
//            return result;
//
//        }
//
//        //1.递归的定义 :返回以node为跟的二叉树的前序遍历
//        private  void preorder(TreeNode node){
//            //3.递归的出口
//            if(node==null)
//                return;
//            //2.递归的拆解
//            result.add(node.val);
//            if(node.left!=null)
//                preorder(node.left);
//            if(node.right!=null)
//                preorder(node.right);
//
//        }
//    }



  // //// way2 递归方式2:分治的思想(divide and conquer)
  //   //1.递归的定义:返回以root为跟的二叉树的前序遍历
  //   class Solution {
  //       public List<Integer> preorderTraversal(TreeNode root) {
  //           List<Integer> result=new ArrayList<Integer>();
  //           //分 divide
  //           List<Integer>left=new ArrayList<Integer>();
  //           List<Integer>right=new ArrayList<Integer>();
  //           if(root==null)
  //               return result;
  //           if(root.left!=null)
  //               left=preorderTraversal(root.left);
  //           if(root.right!=null)
  //               right=preorderTraversal(root.right);
  //           //和 conquer(merge)
  //           result.add(root.val);
  //           result.addAll(left);
  //           result.addAll(right);
  //           return result;
  //       }
  //   }





   // way3 非递归方式


   //通过一个栈,从根节点开始入栈,如果栈不为空,进入循环,出栈访问当前结点,若当前结点的右结点不为空,右结点入栈,若当前结点的左结点不为空,左结点入栈,然后进入下一次循环(因为栈是先进后出  所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点)

   class Solution {
       public List<Integer> preorderTraversal(TreeNode root) {
           List<Integer> result=new ArrayList<Integer>();
           if(root==null)
               return result;
           Stack<TreeNode> stack=new Stack<TreeNode>();
           stack.push(root);
           TreeNode tempNode=null;
           while (!stack.isEmpty()){
               tempNode=stack.pop();
               result.add(tempNode.val);
               //因为栈是先进后出  所以先加入右结点 再加入左结点 弹出的时候先弹出左结点 再弹出右结点
               if(tempNode.right!=null)
                   stack.push(tempNode.right);
               if(tempNode.left!=null)
                   stack.push(tempNode.left);

           }
           return result;
       }
   }

LeetCode 145 Postorder 问题描述

在这里插入图片描述

思路

前序遍历: 按照 左结点 右结点 根节点 的顺序
递归实现 : postorder方法实现按照 左结点 右结点 根节点的顺序加入。以左结点为根的子树和 以右结点为根的子树 遍历也是由postorder方法实现。
非递归实现1 :根节点压栈 当栈不为空,将弹出元素放在第一个(利用LinkedList的 addFirst方法),压栈按照先左结点后右结点的顺序,如此循环
在这里插入图片描述
非递归实现2:在这里插入图片描述
在这里插入图片描述

java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
// //way1 递归
// class Solution {
//         List<Integer> result=new ArrayList<Integer>();
//         public List<Integer> postorderTraversal(TreeNode root) {
//             postorder(root);
//             return result;
//         }
        
//         private  void postorder(TreeNode node){
//             if(node==null)
//                 return;
//             if(node.left!=null)
//                 postorder(node.left);
//             if(node.right!=null)
//                 postorder(node.right);
//             result.add(node.val);

//         }
// }



// way2 非递归方式1
// //根节点压栈  当栈不为空,将弹出元素放在第一个,压栈按照先左结点后右结点的顺序,如此循环
// class Solution {
//     public List<Integer> postorderTraversal(TreeNode root) {
//         LinkedList<Integer> result = new LinkedList<>();
//         if(root == null) return result;
//         TreeNode curr = root;
//         Stack<TreeNode> stack = new Stack<>();
//         stack.push(root);
//         while(!stack.isEmpty()){
//             curr = stack.pop();
//             result.addFirst(curr.val);
//             if(curr.left != null)
//                 stack.push(curr.left);
//             if(curr.right != null)
//                 stack.push(curr.right);
//         }
//         return result;
//     }
// }



// way2 非递归方式2
  class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
            List<Integer> result = new ArrayList<Integer>();
            Stack<TreeNode> stack = new Stack<TreeNode>();
            TreeNode pre = null;//pre用来记录刚刚加入result的结点,可以用来判定右侧是否已经访问过了
            TreeNode current = root;
            while(current != null || !stack.isEmpty()){
                if(current != null){ //当前结点不为空
                    //当前结点入栈
                    stack.push(current);
                    //当前结点指向左结点
                    current = current.left;
                }else{  //当前结点为空
                    //获取栈顶元素
                    TreeNode top = stack.peek();
                    //栈顶结点右侧为空或者右侧已经访问(top.right == pre 说明top.right已经加入res里了)
                    if(top.right == null || top.right == pre){
                        result.add(top.val);//把栈顶的结点加入result中
                        stack.pop();//栈顶的结点弹出
                        pre = top;//pre记录刚刚加入result的结点
                    }else{
                        //栈顶结点右侧不为空且右侧没有被访问
                        current = top.right; //当前结点指向右结点
                    }
                }
            }
            return result;
        }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!