文章目录

  • 二叉树的基本操作-遍历
  • (一)前序遍历(preOrderTraversal)
  • 递归实现
  • 非递归实现
  • (二)中序遍历
  • 递归实现
  • 非递归实现
  • (三)后序遍历
  • 递归实现
  • 非递归实现
  • (四)层序遍历


二叉树的基本操作-遍历

所谓的遍历(Traversal)是指沿着某条搜索路线,依次对树中每个节点均做一次且仅作一次的访问。访问节点后需要进行的操作看具体的问题(比如打印节点内容,数据计算等)。遍历二叉树是其他很多方法的基础,很重要。

二叉树的遍历就前中后和层序遍历四种。前三种有着固定的遍历顺序。

(一)前序遍历(preOrderTraversal)

前序遍历又叫先序遍历。

遍历顺序:根节点、左子树、右子树。

递归实现

//定义树的节点
class TreeNode{
      public char val;
      public TreeNode left;
      public TreeNode right;
      //构造方法
      public TreeNode(char val){
          this.val=val;
      }
      public TreeNode(){

      }
}
public class BinaryTree {

    //比较low的创建方法-穷举法
    public TreeNode createTree(){
        TreeNode A=new TreeNode('A');
        TreeNode B=new TreeNode('B');
        TreeNode C=new TreeNode('C');
        TreeNode D=new TreeNode('D');
        TreeNode E=new TreeNode('E');
        TreeNode F=new TreeNode('F');
        TreeNode H=new TreeNode('H');
        TreeNode I=new TreeNode('I');
        TreeNode G=new TreeNode('G');
        A.left=B;
        A.right=C;
        B.left=D;
        B.right=E;
        C.left=F;
        C.right=G;
        E.right=H;
        return A;
    }

    //前序遍历
    public void preOrderTraversal(TreeNode root){
        if(root==null) return;
        System.out.print(root.val+" ");
        preOrderTraversal(root.left);
        preOrderTraversal(root.right);
    }
}

在TestDemo类中调用打印

public class TestDemo {
    public static void main(String[] args) {
        BinaryTree binaryTree=new BinaryTree();
        TreeNode root=binaryTree.createTree();
        //前序遍历
        System.out.println("前序:");
        binaryTree.preOrderTraversal(root);
        System.out.print("");



    }
}

运行结果如下:

java树递归所有路径 java递归树结构_List

非递归实现

递归实现需要多次调用函数(自己本身),而函数的调用是在栈上进行的。递归隐式的维护了这个栈,非递归就是显式的把这个栈给模拟出来。我们需要用到一种数据结构-队列。

代码如下:
以下代码是将返回值放在了一个list中。

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null) return res;
        Deque<TreeNode> stack=new LinkedList<TreeNode>();
        TreeNode node=root;

        while(node!=null || !stack.isEmpty()){
            while(node!=null){
                res.add(node.val);
                stack.push(node);
                node=node.left;
            }
            node=stack.pop();
            node=node.right;
        }
        return res;
    }
}

(二)中序遍历

遍历顺序:左子树、根节点、右子树

递归实现

//中序遍历
    public void inOrderTraversal(TreeNode root){
        if(root==null){
            return;
        }
        preOrderTraversal(root.left);
        System.out.print(root.val+" ");
        preOrderTraversal(root.right);
    }

同上,代码中省略的部分同上,在类TestDemo中运行结果如下:

java树递归所有路径 java递归树结构_数据结构_02

非递归实现

同上,将代码返回值放在了一个list中。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res=new ArrayList<Integer>();
        if(root==null){
            return res;
        }
        Deque<TreeNode> stack=new LinkedList<TreeNode>();
        TreeNode node=root;
        while(!stack.isEmpty() || node!=null){
            while(node!=null){
                stack.push(node);
                node=node.left;   
            }
            node=stack.pop();//左边为空,就得到栈顶子树的根节点
            res.add(node.val); 
            node=node.right;
        }
        return res;
    }
}

(三)后序遍历

遍历顺序:左子树、右子树、根节点

递归实现

//后序遍历
    public void postOrderTraversal(TreeNode root){
        if(root==null){
            return;
        }
        preOrderTraversal(root.left);
        preOrderTraversal(root.right);
        System.out.print(root.val+" ");
    }

同上,代码中省略的部分同上,在类TestDemo中运行结果如下:

java树递归所有路径 java递归树结构_java_03

非递归实现

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

(四)层序遍历

层序遍历就是先遍历深度为1的根节点,再遍历深度为2的子节点,再遍历深度为3的所有子节点…一直到最后的叶子节点。就是按顺序遍历每一层。

//层序遍历(借助队列)
    void levelOrderTraversal(TreeNode root){
        if(root ==null){
            return;
        }
        Queue<TreeNode> queue=new LinkedList<TreeNode>();
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode top=queue.poll();
            System.out.print(top.val+" ");
            if(top.left!=null){
                queue.offer(top.left);
            }
            if(top.right!=null){
                queue.offer(top.right);
            }
        }
    }

力扣上有道题是要求将每一层遍历节点都放在一起,也就需要你判断出当前节点在哪一层。我们在上面的代码中不难发现,队列的size就是每层的节点数。
所以代码如下:

//层序遍历(借助队列+将每一层的树节点都放到一个list中  leetcode题目)
     public List<List<Integer>> levelOrder(TreeNode root){
        //只是为了满足结果的要求
        List<List<Integer>> res=new ArrayList<>();
        if(root==null){
            return null;
        }

        //队列的作用是用来实现层序遍历的。
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);

        while(!queue.isEmpty()){
            //size的大小就是一层
            int size=queue.size();
            List<TreeNode> list=new ArrayList<>();
            while(size!=0){
                TreeNode top=queue.poll();
               list.add(top.val);
                if(top.left!=null){
                    queue.offer(top.left);
                }
                if(top.right!=null){
                    queue.offer(top.right);
                }
                size--;
            }
            res.add(list);
        }
        return null;
    }