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

来源:互联网 发布:c语言常考题 编辑:程序博客网 时间:2024/05/24 22:46

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);        }    }
0 0
原创粉丝点击