Java 二叉树的三种遍历 - 循环版本


class TreeNode {
    int val;
    public TreeNode left;
    public TreeNode right;


    TreeNode(int val) {
        this.val = val;
    }

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Main {


    public static void main(String[] args) {

        // 数据:这里用了最后一个case,看起来足够复杂
        /*
            1
           / \
           2  3

           null

           1
           \
            2
              \
               3

             1
              \
               2
              / \
              3 4


           1
           /\
          2  3
         / \  \
         4 5   6

         */

//        TreeNode t2 = new TreeNode(2,null,null);
//        TreeNode t3 = new TreeNode(3,null,null);
//        TreeNode t1 = new TreeNode(1,t2,t3);
//
        TreeNode t4 = new TreeNode(4);
        TreeNode t5 = new TreeNode(5);
        TreeNode t6 = new TreeNode(6);
        TreeNode t3 = new TreeNode(3, null, t6);
        TreeNode t2 = new TreeNode(2, t4, t5);
        TreeNode t1 = new TreeNode(1, t2, t3);


//        new Main().inOrder2(t1);
        new Main().postOrder2(t1);
    }


    public void preOrder2(TreeNode root) {
        if (root == null) return;

        LinkedList<TreeNode> list = new LinkedList<>();

        list.add(root);

        while (list.size() > 0) {
            TreeNode head = list.pop();

            if (head == null) {
                continue;
            }

			// 先序遍历最简单,因为可以当场把root处理掉,不必等处理完child之后再回来处理
            list.push(head.right);
            list.push(head.left);
            System.out.println(head.val);
        }

    }

    public void inOrder2(TreeNode root) {
        LinkedList<TreeNode> list = new LinkedList<>();  // top [left, mid, right, ....] tail

        list.add(root);

        while (list.size() > 0) {
            TreeNode head = list.pop();

			// 中序遍历稍微有点复杂,但是这里有个取巧的方法:
			// 每次都先把left走到底
			// 这个方法我个人感觉不容易想到
			// 容易想到的方法是直接硬来!参考下面的函数postOrder2
            while (head != null) {
                list.push(head);
                head = head.left;
            }
			
			// 此时left已经走到头了,就可以像preOrder一样,先处理当前元素了
            if (list.size() > 0) {
                head = list.pop();
                System.out.println(head.val);
                list.push(head.right);
            }
        }

    }

    public void postOrder2(TreeNode root) {
        if (root == null) return;

        LinkedList<TreeNode> list = new LinkedList<>();

		// 后序遍历就不能用前面那个取巧的方法了
		// 但是思路反而容易比较理解
		// 就是按照后序把left right root给push进去
		// 此时关键的地方在于:当我们再次回到root时,怎么知道它的child已经处理过了?
		// 一个方法是用个set来记录所有TreeNode的情况,这样的话,空间复杂度会到O(n),循环也就失去价值了
		// 另外一个方法就是用一个pre变量来记录上一次到了哪个TreeNode
		// 如果pre是当前node的child,说明已经遍历回来了,就可以打印val了
        TreeNode pre = root;
        list.add(root);

        while (list.size() > 0) {
            TreeNode head = list.pop();

            if (head == null) {
                continue;
            }

            if ((head.left == null && head.right == null) || pre == head.left || pre == head.right) {
                System.out.println(head.val);
                pre = head;
                continue;
            }

            list.push(head);
            list.push(head.right);
            list.push(head.left);

            pre = head;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值