算法总结 - 001.二叉树的遍历

文章目录

  • 0. 二叉树的遍历
  • 1. 前序遍历
  • 2. 中序遍历
  • 3. 后序遍历
  • 4. 层序遍历
  • 5. 代码

0. 二叉树的遍历

  • 二叉树的遍历分为前序遍历、中序遍历、后序遍历、层序遍历。
  • 其中,前序遍历、中序遍历、后序遍历分别有递归两种实现方式,层序遍历有队列一种实现方式。
  • 递归实现较为简单,重点在于栈实现,前序遍历和中序遍历的栈实现较为相似,后序遍历的栈实现略有不同,是重中之重。
  • 以下面这颗二叉树为例分别简述四种遍历。

算法总结 - 001.二叉树的遍历_第1张图片

1. 前序遍历

  • 二叉树的前序遍历结果是:1,2,M,N,3,true,false。
  • 前序遍历的访问顺序是根结点-左子树-右子树。
  • 在栈实现中,从根结点1开始,访问完结点后,将结点压入栈中,然后访问结点的左子树2,循环直到左子树为null,此时指针指向整颗二叉树最左端的结点M的左子树,该子树为null。从栈中弹出一个结点,即最左端的结点M,然后令指针指向其右子树,进入下一次循环。当指针指向null且栈也为空时,结束循环。

2. 中序遍历

  • 二叉树的中序遍历结果是:M,2,N,1,true,3,false。
  • 中序遍历的访问顺序是左子树-根结点-右子树。
  • 在栈实现中,与前序遍历相似,不同的是前序遍历在将结点压入栈之前访问结点,而中序遍历是将结点从栈中弹出时访问结点。

3. 后序遍历

  • 二叉树的后序遍历结果是:M,N,2,true,false,3,1。
  • 后序遍历的访问顺序是左子树-右子树-根结点。
  • 按照前序遍历、中序遍历的流程发现没有后序访问结点的时机,但是发现如果将前序遍历的访问顺序改为根结点-右子树-左子树,再将访问顺序整体翻转,就得到了后序遍历的访问顺序。
  • 可以利用LinkedList代替ArrayList访问结点,每次访问时将元素添加到链表头部,再按照根结点-右子树-左子树的顺序进行遍历,即可得到后序遍历的结果。

4. 层序遍历

  • 二叉树的层序遍历结果是:1,2,3,M,N,true,false。
  • 层序遍历的访问顺序是从上往下、从左往右依次访问。
  • 利用队列先进先出的特性可以方便地实现层序遍历。

5. 代码

import java.util.*;

public class Test {
    public static void main(String[] args) {
        TreeNode<Object> node1 = new TreeNode<>(1);
        TreeNode<Object> node2 = new TreeNode<>(2);
        TreeNode<Object> node3 = new TreeNode<>(3);
        TreeNode<Object> node4 = new TreeNode<>("M");
        TreeNode<Object> node5 = new TreeNode<>("N");
        TreeNode<Object> node6 = new TreeNode<>(true);
        TreeNode<Object> node7 = new TreeNode<>(false);
        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        node3.left = node6;
        node3.right = node7;
        System.out.println("前序遍历(栈实现):" + Preorder.stack(node1));
        System.out.println("前序遍历(递归实现):" + Preorder.recur(node1));
        System.out.println("中序遍历(栈实现):" + Inorder.stack(node1));
        System.out.println("中序遍历(递归实现):" + Inorder.recur(node1));
        System.out.println("后序遍历(栈实现):" + Postorder.stack(node1));
        System.out.println("后序遍历(递归实现):" + Postorder.recur(node1));
        System.out.println("层序遍历(队列实现):" + Floor.queue(node1));
    }
}

class TreeNode<T> {
    public T val;
    public TreeNode<T> left;
    public TreeNode<T> right;

    public TreeNode(T val) {
        this.val = val;
    }
}

class Preorder {
    public static <T> List<T> stack(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Deque<TreeNode<T>> stack = new LinkedList<>();
        TreeNode<T> cur = root;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                //TODO
                res.add(cur.val);
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
        return res;
    }

    public static <T> List<T> recur(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        recur(root, res);
        return res;
    }

    private static <T> void recur(TreeNode<T> root, List<T> res) {
        if (root == null) {
            return;
        }
        //TODO
        res.add(root.val);
        recur(root.left, res);
        recur(root.right, res);
    }
}

class Inorder {
    public static <T> List<T> stack(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Deque<TreeNode<T>> stack = new LinkedList<>();
        TreeNode<T> cur = root;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            //TODO
            res.add(cur.val);
            cur = cur.right;
        }
        return res;
    }

    public static <T> List<T> recur(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        recur(root, res);
        return res;
    }

    private static <T> void recur(TreeNode<T> root, List<T> res) {
        if (root == null) {
            return;
        }
        recur(root.left, res);
        //TODO
        res.add(root.val);
        recur(root.right, res);
    }
}

class Postorder {
    public static <T> List<T> stack(TreeNode<T> root) {
        LinkedList<T> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Deque<TreeNode<T>> stack = new LinkedList<>();
        TreeNode<T> cur = root;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                //TODO
                res.addFirst(cur.val);
                stack.push(cur);
                cur = cur.right;
            }
            cur = stack.pop();
            cur = cur.left;
        }
        return res;
    }

    public static <T> List<T> recur(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        recur(root, res);
        return res;
    }

    private static <T> void recur(TreeNode<T> root, List<T> res) {
        if (root == null) {
            return;
        }
        recur(root.left, res);
        recur(root.right, res);
        //TODO
        res.add(root.val);
    }
}

class Floor {
    public static <T> List<T> queue(TreeNode<T> root) {
        List<T> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode<T>> queue = new LinkedList<>();
        queue.offer(root);
        TreeNode<T> cur;
        while (!queue.isEmpty()) {
            cur = queue.poll();
            if (cur != null) {
                //TODO
                res.add(cur.val);
                queue.offer(cur.left);
                queue.offer(cur.right);
            }
        }
        return res;
    }
}

算法总结 - 001.二叉树的遍历_第2张图片

你可能感兴趣的:(算法,#,算法总结,算法)