144. 二叉树的前序遍历

Given a binary tree, return the preorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,2,3]

Follow up: Recursive solution is trivial, could you do it iteratively?

二叉树的先序遍历。

这个比较简单,直接看递归和非递归的代码实现

class Solution {
    
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list=new ArrayList<>();
         process(root,list);
         return list;

    }

    public void process(TreeNode node,List<Integer> list){
        if(node==null){
            return;
        }
        list.add(node.val);
        process(node.left,list);
        process(node.right,list);
    }
}

先序遍历:中左右
非递归的方式用stack来实现(深度优先遍历用stack,广度优先用队列)
对当前节点压入stack,弹出并打印(中),再对cur压入右左(左右)
class Solution {

    public List<Integer> preorderTraversal(TreeNode root) {
         List<Integer> list=new ArrayList<>();
        if(root==null){
            return list;
        }
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
           TreeNode cur=stack.pop();
           list.add(cur.val);
           if(cur.right!=null){
               stack.push(cur.right);
           }
           if(cur.left!=null){
               stack.push(cur.left);
           }
        }
        return list;
    }
}

 

先序遍历还可以用Morris序来遍历

  时间复杂度为O(1) 

Morris遍历细节:
假设cur来到当前节点,cur从头节点开始
1、cur没有左孩子,cur向右移动
2、cur有左孩子,找到左孩子的最右孩子
a:如果右孩子的右指针为空,则让右指针指向当前节点,当前节点向左移动,回到1;(表示第一次到这个节点)
b:如果右孩子的右指针指向当前节点,让右指针指向null,当前节点向右移动;(表示第二次到这个节点)
3、当cur为空遍历结束

这个过程说明了:如果cur有左孩子遍历时会两次经过该节点, 否则只会一次经过该节点

下面是Morris序遍历的代码:
 public void morrisTraversal(TreeNode head){
        if(head==null)
        {
            return;
        }
        TreeNode cur=head;
        TreeNode mostRight;
        while(cur!=null){
            mostRight=cur.left;
            if(mostRight!=null){
                //有左节点
                while (mostRight.right!=null&&mostRight.right!=cur){
                    mostRight=mostRight.right;
                }
                if(mostRight.right==null){
                    mostRight.right=cur;
                    cur=cur.left;
                    continue;
                }else{
                    mostRight.right=null;
                }
            }
            cur=cur.right;
        }
    }

  

Morris序改先序遍历
 public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> list=new ArrayList<>();
            if(root==null){
                return list;
            }
            TreeNode cur=root;
            TreeNode mostRight;
            while(cur!=null){
                mostRight=cur.left;
                if(mostRight!=null){
                    //有左节点
                    while (mostRight.right!=null&&mostRight.right!=cur){
                        mostRight=mostRight.right;
                    }
                    if(mostRight.right==null){
                        //第一次来到cur
                        list.add(cur.val);//注意这行的位置,不能放到下面,因为cur会移动
                        mostRight.right=cur;
                        cur=cur.left;
                        continue;
                    }else{
                        //第二次来到cur
                        mostRight.right=null;
                    }
                }else{
                    //只会来到一次的cur
                    list.add(cur.val);
                }

                cur=cur.right;
            }
            return list;
        }

  

 

posted @ 2021-08-31 21:24  sherry001  阅读(51)  评论(0编辑  收藏  举报