二叉树遍历模板(递归和非递归版本)

栈的推荐写法:
Deque<TreeNode> stack = new LinkedList<>();
JDK文档:虽然 Deque 实现没有严格要求禁止插入 null 元素,但建议最好这样做。建议任何事实上允许 null 元素的 Deque 实现用户最好不 要利用插入 null 的功能。这是因为各种方法会将 null 用作特殊的返回值来指示双端队列为空。

队列的推荐写法:Queue<TreeNode> queue = new LinkedList<>();
优先队列(底层是堆实现的)的推荐写法:
小根堆:PriorityQueue<Integer> queue = new PriorityQueue<>((v1, v2) -> v1 - v2;
java默认使用最小堆,实现大根堆需要重写一下比较器。
大根堆:PriorityQueue<Integer> queue = new PriorityQueue<>((v1, v2) -> v2 - v1;

为了不改变根节点:TreeNode cur = root;
非递归版本的框架:需要一个栈 s 来树中的结点,一个 list 来存储结果集。

整体框架

// 一个栈和一个list
List<Integer> res = new ArrayList<>();
Deque<TreeNode> s = new ArrayDeque<>();
// 为了不改变根节点
TreeNode cur = root;
while (cur != null || !s.isEmpty()) {
    if(cur != null){
		// 处理结点
    }else {
    	cur = s.pop();
    	// 处理结点
    }
}

先序遍历

// 先序
while (cur != null || !s.isEmpty()) {
    if(cur != null){
		s.push(cur);		// 根
		res.add(cur.val);	
		cur = cur.left;		// 左
    }else {
    	cur = s.pop();
    	cur = cur.right;	// 右
    }
}

深度优先遍历

迭代:先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点了。

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> res=new ArrayList<Integer>();
        if(root==null)  return lists;
        Deque<TreeNode> stack = new ArrayDeque<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode cur=stack.pop();      
            if(cur.right!=null)
                stack.push(cur.right);
            if(tree.left!=null)
                stack.push(cur.left);
            res.add(cur.val);
        }
        return res;
    }
}
 public void depthOrderTraversalWithRecursive() {
     depthTraversal(root);
 }

 private void depthTraversal(TreeNode node) {
     if (node!= null) {
         System.out.print(node.value + "  ");
         depthTraversal(node.left);
         depthTraversal(node.right);
     }
 }

中序遍历

// 中序
while (cur != null || !s.isEmpty()) {
    if(cur != null){
		s.push(cur);			
		cur = cur.left;		// 左
    }else {
    	cur = s.pop();
    	res.add(cur.val);	// 根
    	cur = cur.right;	// 右
    }
}

后序遍历

// 后序   左-->右-->根  将前序遍历调整一下 根-->右-->左 
//  然后结果存放到栈里进行倒序, 之后再遍历结果栈就可以输出后序遍历了
while (cur != null || !s.isEmpty()) {
    if(cur != null){
		s.push(cur);			
		resStack.push(cur);		// 根
		cur = cur.right;	// 右
    }else {
    	cur = s.pop();
    	cur = cur.left;	// 左
    }
}
// 遍历结果栈
while(!resStack.isEmpty()){
	res.add(resStack.pop().val);
}

层次遍历

分两种情况,比如下面的树,1.返回一位列表 [3,9,20,15,7]
             2.另一种情况是返回二维列表 [[3],[9,20],[15,7]]
在这里插入图片描述

// 情况1   全部结点加入队列
class Solution {
    public int[] levelOrder(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root == null) return new int[]{};
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();
            res.add(node.val);
            if(node.left != null) queue.add(node.left);
            if(node.right != null) queue.add(node.right);
        }
        int[] ans = new int[res.size()];
        for(int i = 0; i < res.size(); i++){
            ans[i] = res.get(i);
        }
        return ans;  
    }
}

// 情况2   全部结点加入队列
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root == null)    return res;
        queue.offer(root);
        while(!queue.isEmpty()){
            // 临时list
            List<Integer> temp = new ArrayList<>();
            int size = queue.size();
            // 将队列中的元素全部出队
            for(int i = 0; i < size; i++){
                TreeNode node = queue.poll();
                temp.add(node.val);
                // 出队后将其左右孩子加入队列
                if(node.left != null)   queue.offer(node.left);   
                if(node.right != null)   queue.offer(node.right);   
            }
            res.add(temp);
        }
        return res;
    }
}
public class TreeNode {
    int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int x) {
        val = x;
    }

    public TreeNode(int x, TreeNode l, TreeNode r) {
        val = x;
        this.left = l;
        this.right = r;
    }
}

class Solution {
    public List<Integer> preorderTraversal1(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preorder(root, res);
        return res;
    }

    // 递归版本
    public void preorder(TreeNode root, List<Integer> res) {
        if (root == null) return;
        res.add(root.val);
        preorder(root.left, res);
        preorder(root.right, res);
    }

    // 迭代版本
    public List<Integer> preorderTraversal2(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> s = new ArrayDeque<>();
        // 为了不改变根节点
        TreeNode cur = root;
        while (cur != null || !s.isEmpty()) {
            if(cur != null){
                s.push(cur);
                res.add(cur.val);
                cur = cur.left;
            }else {
                cur = s.pop();
                cur = cur.right;
            }
        }
        return res;
    }


    public List<Integer> inorderTraversal1(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        preorder(root, res);
        return res;
    }

    // 递归版本
    public void inorder(TreeNode root, List<Integer> res) {
        if (root == null) return;
        inorder(root.left, res);
        res.add(root.val);
        inorder(root.right, res);
    }


    public List<Integer> inorderTraversal2(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> s = new ArrayDeque<>();
        TreeNode cur = root;
        while (cur != null || !s.isEmpty()) {
            if (cur != null) {
                s.push(cur);
                cur = cur.left;
            } else {
                cur = s.pop();
                res.add(cur.val);
                cur = cur.right;
            }
        }
        return res;
    }


    public List<Integer> postorderTraversal1(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        postorder(root, res);
        return res;
    }

    public void postorder(TreeNode root, List<Integer> res) {
        if(root == null){
            return;
        }
        postorder(root.left, res);
        postorder(root.right, res);
        res.add(root.val);
    }

    // 前序遍历顺序为:根 -> 左 -> 右
    // 后序遍历顺序为:左 -> 右 -> 根
    // 所以, 我们可以把前序遍历的稍作修改: 根 -> 右 -> 左,
    // 然后结果存放到栈里进行倒序, 之后再遍历结果栈就可以输出后序遍历了
    public List<Integer> postorderTraversal2(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> s = new ArrayDeque<>();
        Deque<TreeNode> resStack = new ArrayDeque<>();
        TreeNode cur = root;
        while (cur != null || !s.isEmpty()){
            if (cur != null){
                resStack.push(cur);
                s.push(cur);
                cur = cur.right;
            }else {
                cur = s.pop();
                cur = cur.left;
            }
        }
        while (!resStack.isEmpty()){
            res.add(resStack.pop().val);
        }
        return res;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值