二叉树系列6:非递归遍历

1 非递归中序遍历

    /** * 非递归中序遍历二叉树 */
    public ArrayList<TreeNode> inorderTraversal(TreeNode t) {
        if (t == null) {
            return null;
        }

        Stack<TreeNode> stack = new Stack<>();
        ArrayList<TreeNode> aList = new ArrayList<>();
        TreeNode p = t;
        while (p != null || !stack.isEmpty()) {
            // 如果目前访问的节点不为空,则尝试先访问它的左子树
            if (p != null) {
                stack.push(p);
                // 开始访问左子树
                p = p.left;
            }
            // 如果 p为null说明访问的左节点为空,将先前压入栈的父节点pop,打印,并且开始访问右子树
            else {
                p = stack.pop();
                // 打印父节点
                aList.add(p);
                // 开始访问右子树
                p = p.right;
            }
        }
        return aList;
    }

2 非递归后续遍历

前序和中序差不多,不赘述;然而后续比较麻烦,因为每次栈中的节点要被两次访问(遍历其左子树,再是右子树)之后才能出栈与输出,所以给 TreeNode 增加了一个字段用于记录节点的访问次数。

TreeNode.java

package BinaryTree;

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

    public TreeNode() {
    }

    public TreeNode(int v) {
        val = v;
    }

    public TreeNode(TreeNode l, TreeNode r, int v) {
        left = l;
        right = r;
        val = v;
    }

}

BinaryTreeTest.java

    /** * 非递归的后续遍历 */
    public ArrayList<TreeNode> postorderTraveral(TreeNode t) {
        if (t == null) {
            return null;
        }

        Stack<TreeNode> stack = new Stack<>();
        ArrayList<TreeNode> aList = new ArrayList<>();
        TreeNode p = t;
        while (p != null || !stack.isEmpty()) {
            if (p != null) {
                // 后面的逻辑要保证进入这个代码块的 p 都是新的节点
                p.visitedNum = 1; // 表示已经访问过 1 次了
                stack.push(p);
                p = p.left;
            } else {
                p = stack.peek();
                // visitedNum等于1说明它的左子树虽然已经访问过了,但是它的右子树还没有访问,所以不能出栈;
                // 而是先去尝试访问它的右子树
                if (p.visitedNum == 1) {
                    p.visitedNum = 2; // 表示它的右子树已经访问过了
                    p = p.right;
                }
                // 如果它的左右子树都已经访问过了,则输出
                else if (p.visitedNum == 2) {
                    p = stack.pop(); // 把这个左右子树都访问过的节点出栈并输出
                    aList.add(p);
                    p = null; // 处理完一个子树后,就要从栈中取父节点;
                    // 然后判断它被访问过几次,所以留待下次循环处理,将其赋值为null,则是从栈中重新取
                }
            }
        }
        return aList;

    }

3 测试

    public static void main(String[] args) {

        /** * 通过插入新建了一个二叉搜索树 * 8 * / \ * 3 22 * \ / \ * 5 13 27 * \ * 7 * */ 
        TreeNode binarySearchTree = new TreeNode(8);
        BinaryTreeTest testTree = new BinaryTreeTest();
        testTree.add(binarySearchTree, 22);
        testTree.add(binarySearchTree, 3);
        testTree.add(binarySearchTree, 13);
        testTree.add(binarySearchTree, 5);
        testTree.add(binarySearchTree, 7);
        testTree.add(binarySearchTree, 27);
        ArrayList<TreeNode> aList = testTree.postorderTraveral(binarySearchTree);
        System.out.println("后续遍历的结果是:");
        for (TreeNode treeNode : aList) {
            System.out.printf("%-5d", treeNode.val);
        }
        System.out.println();

        aList = testTree.inorderTraversal(binarySearchTree);
        System.out.println("中续遍历的结果是:");
        for (TreeNode treeNode : aList) {
            System.out.printf("%-5d", treeNode.val);
        }


    }

你可能感兴趣的:(二叉树,中序遍历,后序遍历,前序遍历,非递归遍历)