二叉树的前序、中序、后序非递归遍历

二叉树的前序、中序、后序非递归遍历

今天去面试,刚进去就让写一下二叉树的前序非递归遍历,当场有点蒙,虽然以前看过很多遍,但是时间长还是会忘,因此再写篇博客,加深印象,也算是一个小总结。

思路:无论遇到什么样的算法题,思路很重要,即使自己没见过的或者是做过又忘了的,都不要慌,冷静下来分析一下。例如,想想二叉树的结构,若想先序遍历,肯定要记录下之前走过的节点,那么肯定要用到栈,剩下的主要考虑什么时候节点进栈,什么时候节点出栈,什么时候访问节点,只要搞清楚这三点,基本就可以实现了。

  1. 看下图,首先肯定是要根节点入栈的,之后先走它的左分支,并且需要记录所走过的节点,也就是将每个走过的节点入栈,由于是先序遍历,那么应该在入栈的时候就去访问节点。
  2. 最关键的就是出栈的条件不好考虑,试想什么时候该出栈呢?应该是左孩子为空,或者左边的分支都已经访问过了,而且在根节点出栈后,要将它的右孩子进栈,访问右子树,以此类推。看图看代码。

这里写图片描述

//前序遍历二叉树-非递归
public static void preTraversalBinarytree(TreeNode root){
        Stack<TreeNode> stack = new Stack<TreeNode>();

        if(root == null)
            return;

        stack.push(root); //根节点进栈
        while(!stack.isEmpty()){
            TreeNode node = stack.peek();

            if(node != null){
                System.out.print(node.val); //访问节点
                stack.push(node.left); //左孩子进栈
            }
            else{
                stack.pop(); //空指针出栈
                if(!stack.isEmpty()){
                    TreeNode node2 = stack.pop(); //节点出栈
                    stack.push(node2.right); //右孩子进栈
                }else{
                    break;
                }
            }
        }
        System.out.println();

    }

对于中序遍历和先序遍历非常像,只是改变访问节点的时间而已,在出栈的时候访问节点即可。

后序遍历二叉树的思路:这个比前两个要难,很难想到思路,要想先遍历左孩子和右孩子,后遍历父节点,还是需要用栈保存路径,先走左子树,一直走到左子树为空,然后再看栈顶节点的右孩子,若右孩子不为空,让右孩子进栈,再把右孩子当成当前节点,去找它所有的左孩子和右孩子;很重要的是需要记录当前节点和上一个访问过得节点,所以多增加了两个变量curr和previsited,什么时候节点出栈呢?应该是右孩子为空,或者右孩子是刚刚被访问过的节点,那么这时自己没什么存在价值了,乖乖出栈。大家看代码的时候,可以画一下示意图,看着代码走一遍流程,就能明白思路了。

//后序遍历二叉树
public static void postTraversalBinaryTree(TreeNode root){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode curr = root;
        TreeNode previsited = null;
        while(curr != null || !stack.isEmpty()){
            while(curr != null){
                stack.push(curr);  //入栈
                curr = curr.left;
            }

            curr = stack.peek();//只取值不pop哦

            if(curr.right == null || curr.right == previsited){ //出栈的条件
                System.out.print(curr.val);
                previsited = curr;
                stack.pop();
                curr = null;
            }else{
                curr = curr.right;
            }
        }

    }

完整的代码,包括树的定义,简单的创建以及三种非递归遍历如下:

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x){
        val = x;
    }   
}
//上面的TreeNode是单独的一个类

package Tree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class traversalBinaryTree {

    public static TreeNode createTree(){
        TreeNode root = new TreeNode(1);
        TreeNode node1 = new TreeNode(2);
        TreeNode node2 = new TreeNode(3);
        root.left = node1;
        root.right = node2;

        TreeNode node3 = new TreeNode(4);
        TreeNode node4 = new TreeNode(5);
        node1.left = node3;
        node1.right = node4;

        TreeNode node5 = new TreeNode(6);
        TreeNode node6 = new TreeNode(7);
        node2.left = node5;
        node2.right = node6;

        TreeNode node7 = new TreeNode(8);
        node3.left = node7;

        return root;
    }

public static void PrintTree(TreeNode root){  //   按层次打印
         Queue<TreeNode> queue = new LinkedList<TreeNode>();

         if(root == null)
             return;

         queue.add(root);
         queue.add(null);
         while(!queue.isEmpty()){
             TreeNode node = queue.poll();
             if(queue.isEmpty())
                 break;
             if(node == null){
                 System.out.println();
                 queue.add(null);
                 continue;
             }
             else
                 System.out.print(node.val+"   ");
             if(node.left!=null){
                 queue.add(node.left);
             }
             if(node.right!=null){
                 queue.add(node.right);
             }
         }
         System.out.println();
    }

    //前序遍历二叉树-非递归
public static void preTraversalBinarytree(TreeNode root){
        Stack<TreeNode> stack = new Stack<TreeNode>();

        if(root == null)
            return;

        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.peek();

            if(node != null){
                System.out.print(node.val);
                stack.push(node.left);
            }
            else{
                stack.pop();
                if(!stack.isEmpty()){
                    TreeNode node2 = stack.pop();
                    stack.push(node2.right);
                }else{
                    break;
                }

            }

        }
        System.out.println();

    }

    //中遍历二叉树-非递归
 public static void midTraversalBinarytree(TreeNode root){
            Stack<TreeNode> stack = new Stack<TreeNode>();

            if(root == null)
                return;

            stack.push(root);
            while(!stack.isEmpty()){
                TreeNode node = stack.peek();

                if(node != null){
                    stack.push(node.left);
                }
                else{
                    stack.pop();
                    if(!stack.isEmpty()){
                        TreeNode node2 = stack.pop();
                        System.out.print(node2.val);
                        stack.push(node2.right);
                    }else{
                        break;
                    }

                }

            }

            System.out.println();
        }

    //后序遍历二叉树
public static void postTraversalBinaryTree(TreeNode root){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode curr = root;
        TreeNode previsited = null;
        while(curr != null || !stack.isEmpty()){
            while(curr != null){
                stack.push(curr);
                curr = curr.left;
            }

            curr = stack.peek();

            if(curr.right == null || curr.right == previsited){
                System.out.print(curr.val);
                previsited = curr;
                stack.pop();
                curr = null;
            }else{
                curr = curr.right;
            }
        }

    }


    public static void main(String[] args){

        TreeNode root = createTree();
        PrintTree(root);
        preTraversalBinarytree(root);
        midTraversalBinarytree(root);
        postTraversalBinaryTree(root);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值