数据结构 二叉树的四种遍历方式(基础面试题)

目录

一、二叉树的前序遍历

1、递归求法

2.非递归求法

二、二叉树的中序遍历

1.递归求法

2.非递归求法

三、二叉树的后序遍历

1.递归求法

2.非递归求法

四、二叉树的层序遍历

1.迭代求法


一、二叉树的前序遍历

1、递归求法

 public void preOrder(Node root){
        if(root==null){
            return;
        }
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
}

2.非递归求法

  通过栈和链表实现,先将根节点入栈,然后再循环弹出栈顶元素并加入到链表,同时判断栈顶元素的右孩子和左孩子是否为空(注意一定是先让右孩子入栈再左孩子!!!因为栈是先进后出,而先序遍历是根左右,需要先打印左孩子,所以让左孩子后入栈就可以先打印左孩子),如果不为空就入栈,为空就不入栈,以此循环知道栈为空结束。


import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class Num144 {
    //先序遍历的非递归实现
    List<Integer> ret=new LinkedList<>();
    public List<Integer> preorderTraversal(TreeNode root) {
        if(root==null){
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode treeNode = stack.pop();
            ret.add(treeNode.val);
            //先入右孩子,因为栈是先入后出,先序遍历要后打印右孩子,所以让右孩子先入
            if (treeNode.right != null) {
                stack.push(treeNode.right);
            }
            if(treeNode.left!=null){
                stack.push(treeNode.left);
            }
        }
        return ret;
    }
}

二、二叉树的中序遍历

1.递归求法

   public void inOrder(Node root){
        if(root==null){
            return;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

2.非递归求法

  通过栈和链表来实现,引入cur引用,cur表示当前要处理的节点,让cur先指向root,然后开始在cur不为空的情况下循环将cur入栈,并让cur不断指向cur.left,直到cur.left为空(左处理完毕)就将栈顶元素弹出并加入到链表中(根节点处理完毕),再让cur指向cur.right(处理cur.right),如果cur.right为空,则再次弹出栈顶元素,并加入链表,如果不为空,就开始对cur,right进行处理,以此循环,直到栈为空。

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class Num94 {
    List<Integer> ret=new LinkedList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) {
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        TreeNode cur=new TreeNode();
        cur=root;
        while (cur!=null || !stack.isEmpty()){
            while (cur!=null) {
                stack.push(cur);
                cur=cur.left;
            }
            TreeNode node = stack.pop();
            ret.add(node.val);
            cur = node.right;
        }
        return ret;
    }
}

三、二叉树的后序遍历

1.递归求法

 public void postOrder(Node root){
        if(root==null){
            return;
        }
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

2.非递归求法

  通过栈和链表来实现,引入cur和prev引用,cur表示当前要处理的节点,prev表示最近一次已经访问过的节点。先将cur指向root,prev指向空,然后开始在cur不为空的情况下将cur循环入栈,并让cur=cur.left,直到cur.left为空,(左子树处理完毕)然后将栈顶元素暂时出栈,判断栈顶元素的右子树是否为空或者是刚刚最近一次处理过的节点,若是,就栈顶元素的右子树就不需要再处理,将栈顶元素加入到链表中,(右子树处理完毕),并且将prev置为当前的栈顶元素也就是cur,将cur置为空,使其继续处理现在的栈顶元素,若并不是,则将刚刚暂时出栈的栈顶元素再压入栈,并将cur=cur.right,使其循环处理右节点。

import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class Num145 {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ret=new LinkedList<>();
        if(root==null){
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        //当前需要处理的节点
        TreeNode cur=root;
        //最近一次已经访问过的节点
        TreeNode prev=null;
        while (cur!=null || !stack.isEmpty()){
            while (cur!=null){
                stack.push(cur);
                cur=cur.left;
            }
            cur=stack.pop();
            if(cur.right==null || prev==cur.right){
                ret.add(cur.val);
                prev=cur;
                cur=null;
            }else {
                stack.push(cur);
                cur=cur.right;
            }
        }
        return ret;
    }
}

四、二叉树的层序遍历

1.迭代求法

思路:使用队列,将根节点先入队列,然后在队列不为空的前提下开始循环,需要每一层中所有元素的左右节点都入队,因此每次出队一个元素,将他存入这一层的链表中并将他的左右节点在不为空的情况下入队,这一层的循环结束后,将这一层的链表存入总的大链表中,最终队列为空大的循环结束,返回这个大的链表,就得到了二叉树层序遍历的结果。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Num102 {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret=new LinkedList<>();
        if(root==null){
            return ret;
        }
        Queue<TreeNode> queue=new LinkedList<>();//使用LinkedList由于我们要频繁的进行插入和删除操作
        queue.offer(root);
        while (!queue.isEmpty()) {
            List level=new LinkedList();
            int size=queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode cur=queue.poll();
                level.add(cur.val);
                if(cur.left!=null){
                    queue.offer(cur.left);
                }
                if(cur.right!=null){
                    queue.offer(cur.right);
                }
            }
            ret.add(level);
        }
      return ret;
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值