LeetCode刷题Easy篇二叉树遍历

题目

二叉树的前序,中序,后序遍历

Example Tree

Depth First Traversals:
(a) Inorder (Left, Root, Right) : 4 2 5 1 3
(b) Preorder (Root, Left, Right) : 1 2 4 5 3
(c) Postorder (Left, Right, Root) : 4 5 2 3 1

Breadth First or Level Order Traversal : 1 2 3 4 5

https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/

递归解法


    /* Given a binary tree, print its nodes according to the 
      "bottom-up" postorder traversal. */
    void printPostorder(Node node) 
    { 
        if (node == null) 
            return; 
  
        // first recur on left subtree 
        printPostorder(node.left); 
  
        // then recur on right subtree 
        printPostorder(node.right); 
  
        // now deal with the node 
        System.out.print(node.key + " "); 
    } 
  
    /* Given a binary tree, print its nodes in inorder*/
    void printInorder(Node node) 
    { 
        if (node == null) 
            return; 
  
        /* first recur on left child */
        printInorder(node.left); 
  
        /* then print the data of node */
        System.out.print(node.key + " "); 
  
        /* now recur on right child */
        printInorder(node.right); 
    } 
  
    /* Given a binary tree, print its nodes in preorder*/
    void printPreorder(Node node) 
    { 
        if (node == null) 
            return; 
  
        /* first print data of node */
        System.out.print(node.key + " "); 
  
        /* then recur on left sutree */
        printPreorder(node.left); 
  
        /* now recur on right subtree */
        printPreorder(node.right); 
    } 

前序非递归解法

我的尝试:

我的尝试问题有问题,我在while循环的时候把左侧节点都存入list,我以为这些左侧节点都是root,只要从stack取出来,然后添加上右侧节点就可以了,其实不对,比如在 1-null-2-3,情况下,加入list的节点是右侧节点2,不是左侧节点,因为没有左侧节点。如下图所示:

所以这个情况下, 我的输出结果多一个2.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        Stack<TreeNode> stack=new Stack<TreeNode>();
        TreeNode curr=root;
        while(curr!=null){
            list.add(curr.val);
            stack.push(curr);
            //[1,null,2,3],left不存在情况无法cover
            if(curr.left!=null){
                 curr=curr.left;
            }
            else{
                curr=curr.right;
            }
           
        }
        while(stack.empty()==false){
            TreeNode tmpNode=(TreeNode)stack.pop();
            TreeNode tmpRight=tmpNode.right;
            if(tmpRight!=null){
                 list.add(tmpRight.val);
            }
          
            
        }
        return list;
        
        
    }
}

正确解法:

在重新整理思路后,写了如下算法,一次通过leetcode测试,为自己喝彩!!!

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        if(root==null) return list;
        Stack<TreeNode> stack=new Stack<TreeNode>();
        TreeNode curr=root;
        list.add(curr.val);
        if(curr.right!=null){
             stack.push(curr.right);
        }
        if(curr.left!=null){
            stack.push(curr.left);
        }          
        while(stack.empty()==false){
            TreeNode tmpNode=(TreeNode)stack.pop();
            list.add(tmpNode.val);
            if(tmpNode.right!=null){
                 stack.push(tmpNode.right);
            }
             if(tmpNode.left!=null){
                 stack.push(tmpNode.left);
            }
          
            
        }
        return list;
        
        
    }
}

我写的代码可以优化一下,第一段判断右左是否存在,并且入stack的操作,跟后面孩子节点的代码其实是重复的 ,优化整合一下:

1. 判断根节点是否为空,为空,返回空list,不为空,入stack

2. 循环从stack取出stack顶部元素,先访问该node,然后判断是否有左右节点,如果有,先入右,后入左。直到为空

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList();
        if(root==null) return list;
        Stack<TreeNode> stack=new Stack<TreeNode>();
        stack.push(root);        
        while(stack.empty()==false){
            TreeNode tmpNode=(TreeNode)stack.pop();
            list.add(tmpNode.val);
            if(tmpNode.right!=null){
                 stack.push(tmpNode.right);
            }
             if(tmpNode.left!=null){
                 stack.push(tmpNode.left);
            }
          
            
        }
        return list;
        
        
    }



    public List<Integer> postorderTraversal(TreeNode root) {
        //不可以写list,方法addFirst找不到
      LinkedList<Integer> list=new LinkedList<>();
      Stack<TreeNode> stack=new Stack();
      if(root==null){
          return list;
      }
      stack.push(root);
      while(!stack.isEmpty()){
          TreeNode treeNode=stack.pop();
          //为了反转list,所以利用linkedlist的addFirst接口
          list.addFirst(treeNode.val);
          if(treeNode.left!=null){
              stack.push(treeNode.left);
          }
          if(treeNode.right!=null){
              stack.push(treeNode.right);
          }  
      }
    return list;            
   
}
}

中序非递归解法

中序遍历,写对了两个关键部分代码:

一个是指针curr从root开始,一直左侧遍历到底,直到为空,第二个是stack弹出元素,访问。但是不知道怎么处理右侧节点。看了solution后,恍然大悟。修改curr指向curr.right。

整理思路后,写代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        Stack<TreeNode> stack=new Stack();
        List<Integer> list=new ArrayList();
        TreeNode curr=root;
        while(curr!=null||!stack.isEmpty()){
            //如果右子树不为空,又是从左侧一路到底
            while(curr!=null){
                stack.push(curr);
                curr=curr.left;
            }
            curr=stack.pop();
            list.add(curr.val);
            //我的代码只是少这个关键一行,处理右子树
            curr=curr.right;
            
        }
        return list;
    }
}

注意:

stack.pop()弹出的对象也是curr,就是当前指针指向的对象。我刚开始写的时候新定义了一个TreeNode。

后序非递归写法

后序非递归写法,于先序遍历相似,先序遍历是从顶到底,先左后右,后序遍历是从底到顶,先左后右。

所以需要反转,为了便于比较,我把代码放在先序遍历中。

猜你喜欢

转载自blog.csdn.net/hanruikai/article/details/84400610