二叉树的递归和非递归遍历

树节点的基本结构:

  public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode() {}
      TreeNode(int val) { this.val = val; }
      TreeNode(int val, TreeNode left, TreeNode right) {
          this.val = val;
          this.left = left;
          this.right = right;
    }
  }

1.先序遍历:

遍历顺序:根-左孩子-右孩子

1.1 递归算法:

class Solution {
    List<Integer> res;
    public List<Integer> preorderTraversal(TreeNode root) {
        res = new LinkedList<Integer>();
        preTraver(root);
        return res;
    }
    public void preTraver(TreeNode root) {
        if(root != null) {
            res.add(root.val);
            preTraver(root.left);
            preTraver(root.right);
        }
    }
}

1.2 非递归算法:

使用栈来做。最外面用root变量来保存左孩子。root不为空,则直接入栈,并记录下当前值(因为先序遍历是先遍历根);如果root为空,说明此时栈顶结点应该遍历右孩子,则出栈,并遍历右孩子。

class Solution {
    List<Integer> res;
    public List<Integer> preorderTraversal(TreeNode root) {
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        List<Integer> res = new ArrayList<Integer>();
        while(root!=null || !stack.isEmpty()) {
            if(root != null) {
                stack.addFirst(root);
                res.add(root.val);
                root = root.left;
            } else {
                TreeNode p = stack.pollFirst();
                if(p.right != null) {
                    root = p.right;
                }
            }
        }
        return res;
    }
}

2.中序遍历

遍历顺序:左孩子-根-右孩子

2.1 递归算法:

使用栈来做。最外面用root变量来保存左孩子。root不为空,则直接入栈;如果root为空,说明此时栈顶结点应该遍历右孩子。

class Solution {
    List<Integer> res;
    public List<Integer> inorderTraversal(TreeNode root) {
        res = new ArrayList<Integer>();
        inorderTraver(root);
        return res;
    }
    public void inorderTraver(TreeNode root) {
        if(root != null) {
            inorderTraver(root.left);
             res.add(root.val);
            inorderTraver(root.right);
           
        }
    }
}

2.2 非递归算法:

使用栈来做。最外面用root变量来保存左孩子。root不为空,则直接入栈;如果root为空,说明此时栈顶结点应该遍历右孩子,则出栈,记录下当前结点的值(因为中序遍历是先遍历左孩子,然后才是根),然后遍历右孩子。

与先序遍历基本相同,唯一不同的地方在于何时记录结点值。先序遍历是入栈的时候记录结点值,中序遍历时出栈的时候记录结点值。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        while(root!=null || !stack.isEmpty()) {
            if(root != null) {
                stack.addFirst(root);
                root = root.left;
            } else {
                TreeNode p = stack.poll();
                res.add(p.val);
                root = p.right;
            }
        }
        return res;
    }
}

3. 后序遍历

遍历顺序:左孩子-右孩子-根

3.1 递归算法

class Solution {
    List<Integer> res;
    public List<Integer> postorderTraversal(TreeNode root) {
        res = new ArrayList<Integer>();
        posTraver(root);
        return res;
    }
    public void posTraver(TreeNode root) {
        if(root != null) {
            posTraver(root.left);
            posTraver(root.right);
            res.add(root.val);
        }
    }
}

3.2 非递归算法

考虑到,先序遍历是(根-左孩子-右孩子)、后序遍历是(左孩子-右孩子-根)因此可以再先序遍历的基础上进行改进,改成(根-右孩子-左孩子),然后进行逆置操作。对于ArraList可以采用Collections.reverse(res)来进行逆置。

class Solution {
    
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        while(root != null || !stack.isEmpty()) {
            if(root != null) {
                stack.addFirst(root);
                res.add(root.val);
                root = root.right;
            } else {
                TreeNode p = stack.pollFirst();
                root = p.left;
            }
        }
        Collections.reverse(res);
        return res;
    }
}

4. 层序遍历

4.1 递归算法

记录下当前结点位于第几层,先后遍历左右结点。

class Solution {
    List<List<Integer>> res;
    public List<List<Integer>> levelOrder(TreeNode root) {
        res = new ArrayList<List<Integer>>();
        if(root == null) {return res;}
        levelTravel(root, 0);
        return res;
    }
    public void levelTravel(TreeNode root, int level) {
        if(root == null) {
            return ;
        } 
        List<Integer> temp ;
        if(level >= res.size()) {
          temp  = new ArrayList<Integer>();
          res.add(temp);
        } else {
            temp = res.get(level);
        }
        temp.add(root.val);
        levelTravel(root.left,level +1);
        levelTravel(root.right,level +1);
        
    }
}

4.2  非递归算法

采用队列来做。

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if(root == null) {return res;}
        Deque<TreeNode> queue = new LinkedList<TreeNode>();
        queue.addFirst(root);
        int n = 1;
        while(!queue.isEmpty()) {
            n = queue.size();
            List<Integer> temp = new ArrayList<Integer>();
            for(int i = 1; i <= n; i++) {
                TreeNode p = queue.pollLast();
                temp.add(p.val);
                if(p.left != null) {
                    queue.addFirst(p.left);
                } 
                if(p.right != null) {
                    queue.addFirst(p.right);
                } 
            }
            res.add(temp);
        }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值