二叉树的遍历

一、深度优先遍历二叉树

1.前序遍历

1.1.递归遍历

1.1.1.思路

递归遍历二叉树相对简单:

  1. 考虑特殊情况:当根节点为空的时候,直接返回null
  2. 如果根不为空,则将根的值添加进入List
  3. 判断左右节点是否为空,非空则开始递归
  4. 递归的方法:用于判断是否还有左右节点,添加节点的值,有节点则继续递归,没有则返回上一个节点
    DFS()参数:node.left,node.right
    无返回值,因为List是引用类型,所以不用返回值,直接添加值

1.1.2.代码

点击查看代码
//递归 二叉树的前序遍历
import java.util.LinkedList;
import java.util.List;

class Solution2 {
    //定义一个链表用来接收答案
    LinkedList<Integer> list = new LinkedList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        //考虑特殊情况
        if(root==null)return list;
        list.add(root.val);
        //如果左边不为空就先对左边进行深度优先查询
        if (root.left != null) {
            DFS(root.left);
        }
        if (root.right != null) {
            DFS(root.right);
        }
        return list;
    }
    //1\首先处理传入的值
    //2\在进行下一步判断和调用递归
    public void DFS(TreeNode node) {
        list.add(node.val);
        if (node.left!= null) {
            DFS(node.left);
        }
        if (node.right != null) {
            DFS(node.right);
        }
    }
}

1.2.迭代遍历

1.2.1.思路

相对与递归,迭代会更麻烦:
1.
2.

1.2.2.代码

点击查看代码
//不用递归,而是用迭代查询

import java.util.*;

class Solution1 {
    //定义一个栈(stack已经过时,而deque是stack的升级版),用来存储节点,目的是可以返回上一个节点
    //定义一个链表,用来存储节点的值,最后的答案
    public List<Integer> preorderTraversal(TreeNode root) {
        LinkedList<Integer> list=new LinkedList<>();
        //特殊情况
        if(root==null)return list;
        Deque<TreeNode> stack=new LinkedList<>();
        stack.push(root);
        TreeNode node=root;
        //这里是重点,如果node是空,则将栈中节点推出,返回上一个节点
        //如果node非空,则推入栈中方便返回上一个节点,继续向左边遍历
        while(!stack.isEmpty()){
            while(node!=null){
                list.add(node.val);
                stack.push(node);
                node=node.left;
            }
            node=stack.pop();
            node=node.right;
        }
        return list;
    }
}

2.中序遍历

2.1.递归遍历

2.1.1.思路

与前序遍历的思路一样,但是添加值的位置改变了:

2.1.2.代码

点击查看代码
class Solution3 {
    public List<Integer> inorderTraversal(TreeNode root) {
        LinkedList<Integer> list = new LinkedList<>();
        if (root == null) return list;
        if (root.left != null) {
            DFS(root.left, list);
        }
        list.add(root.val);
        if (root.right != null) {
            DFS(root.right, list);
        }
        return list;
    }
    private void DFS(TreeNode node, LinkedList<Integer> list) {
        if (node.left != null) {
            DFS(node.left, list);
        }
        list.add(node.val);
        if (node.right != null) {
            DFS(node.right, list);
        }
    }
}

3.后序遍历

3.1.递归遍历

3.1.1.思路

与前面的前序遍历和中序遍历相差不大,依然是换了添加值的位置:


3.1.2.代码

点击查看代码
//后续遍历,递归
import java.util.LinkedList;
import java.util.List;

class Solution4 {
    public List<Integer> postorderTraversal(TreeNode root) {
        LinkedList<Integer> list=new LinkedList<>();
        if(root==null)return list;
        if(root.left!=null)DFS(root.left,list);
        if(root.right!=null)DFS(root.right,list);
        list.add(root.val);
        return list;
    }
    private void DFS(TreeNode node,List<Integer> list){
        if(node.left!=null)DFS(node.left,list);
        if(node.right!=null)DFS(node.right,list);
        list.add(node.val);
    }
}

二、广度优先遍历二叉树

1.层序遍历

1.1思路

使用广度优先进行遍历:

  1. 第一步依然是考虑特殊情况
  2. 创建一个队列和一个链表,队列用于添加节点,链表用来添加答案
  3. 首先将根节点添加进答案
  4. 创建一个while循环,只要队列不为空,则不断将节点的值添加进答案中
  5. 在while里面创建一个for循环,每次遍历poll出树的一层节点,并添加下一层节点(在for前面要提前声明一个size来得到当前层的节点数,第一次遍历在这里卡了好久)

1.2代码

点击查看代码
class Solution2 {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        LinkedList<List<Integer>> answer = new LinkedList<>();
        if (root == null) return answer;
        queue.add(root);

        LinkedList<Integer> rootlist = new LinkedList<Integer>();
        rootlist.add(root.val);
        answer.add(rootlist);

        while (!queue.isEmpty()) {
//            LinkedList<Integer> list=new LinkedList<>();
//            while(!queue.isEmpty()) {1
//                node = queue.poll();
//                if (node.left != null) {
//                    list.add(node.left.val);
//                }
//                if (node.right != null) {
//                    list.add(node.right.val);
//                }
//                queue.add(node.left);
//                queue.add(node.right);
//                if (!list.isEmpty()) answer.add(list);
//
//            }
//遇到的问题:如何让一个list添加一层的节点的值而不是一个节点下面的两个节点的值的值?
            LinkedList<Integer> list = new LinkedList<>();
//可以利用queue.size,指定一个size次的for循环,这样poll()出去的节点就是上一层的所有节点
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                if (node.left != null) {
                    list.add(node.left.val);
                    queue.add(node.left);
                }
                if (node.right != null) {
                    list.add(node.right.val);
                    queue.add(node.right);
                }
            }
//而list内的值也是当前层的值
            if (!list.isEmpty()) answer.add(list);
//一次for之后,queue里面的节点是当前层的节点,因为上一层的size个节点已经被poll()出去了
        }
        return answer;
    }
}

三、文章内容的梳理

二叉树的遍历

相关练习可以在LeetCode上面找到

上一篇:(转)springAOP解析-2


下一篇:第二章 链表 删除带头结点的单链表值为x的节点并释放其空间