二叉树后序遍历

二叉树后序遍历

后序遍历
顺序为:左子树->右子树->跟节点
先遍历左子树,然后遍历右子树,最后遍历跟节点,以此轮推,直到遍历所有节点

                            6
                     -------------
                     4           8
                 --------     -------
                 2      5     7     9
              --------
              1      3

如上后序遍历的结果为:1 3 2 5 4 7 9 8 6

后序遍历的逻辑如下:
1.二叉树能直接访问的只有跟节点,所有第一步拿到跟节点6是必须的,但是目的并不是访问它,而是需要获取跟节点6的最深的左子树,通过递归或者迭代,得到左子树节点4,节点4的左子树2,节点2的左子树节点1,节点1即为我们第一个要访问的节点

2.节点1没有子节点,所以节点2左子树上所有节点(1) 已访问,然后回溯到节点1的父节点2(此时不访问节点2的值),父节点2有右子树节点3,则访问右子树节点3

3.节点2 左子树、右子树下的所有节点(1, 3)都已访问,此时访问节点2,获取节点2的值

4.节点4左子树下的所有节点(1, 3, 2) 都已访问,则访问节点4的右子树节点5

5.节点4 左子树、右子树下的所有节点(1, 3, 2, 5) 都已访问,此时访问节点4,获取节点4的值

6.节点6左子树下的所有节点(1, 3, 2, 5, 4) 都已访问,此时访问节点6的右子树,拿到节点8但是不访问节点8,而是递归或迭代到节点8最深的左子树节点7,访问节点7

7.节点8左子树下所有节点(7)已访问,则访问节点8的右子树节点9

8.节点8左子树、右子树下的所有节点(7, 9) 都已访问,此时访问节点8,获取节点8的值

9.节点6左子树、右子树下的所有节点(1, 3, 2, 5, 4, 7, 9, 8) 都已访问,此时访问节点6,获取节点6的值

10.至此二叉树的所有节点(1, 3, 2, 5, 4, 7, 9, 8, 6)都已访问,二叉树后续遍历结束

后序遍历的两种方式:递归实现、迭代实现

递归实现如下

        public IList<int> PostorderTraversal(TreeNode root)
        {
            // 集合存储访问到的节点值
            List<int> list = new List<int>();
            // 调用递归函数
            PostorderTraversal(root, list);
            return list;
        }

        // 递归实现
        public void PostorderTraversal(TreeNode root, List<int> list)
        {
            if (null == root)
            {
                return;
            }

            // 递归调用左子树
            PostorderTraversal(root.left, list);

            // 递归调用右子树
            PostorderTraversal(root.right, list);

            // 将节点的值存储到集合中
            list.Add(root.val);
        }

迭代实现如下

        // 迭代实现
        public Stack<int> PostorderTraversal3(TreeNode root)
        {
            // 下面使用两个栈Stack结构
            // 将节点按照 跟->左->右 次序放入栈 stack
            // 然后将节点从栈stack 中出栈,放入栈resultStack
            // 栈resultStack即为我们需要的结果

            // 利用栈存储访问到的节点值
            // 我们需要得到的顺序为  左->右->跟
            // 如果我们按照  跟->右->左 的方式将节点存入栈中
            // 则依次将结果出栈得到的结果即为我们需要的次序: 左->右->跟
            Stack<int> resultStack = new Stack<int>();
            if (null == root)
            {
                return resultStack;
            }

            Stack<TreeNode> stack = new Stack<TreeNode>();
            // 将跟节点入栈
            stack.Push(root);
            while (stack.Count > 0)
            {
                // 节点出栈
                TreeNode node = stack.Pop();
                // 将 stack 出栈的节点值存入 resultStack
                resultStack.Push(node.val);

                // 如果左子树不为空,则将左子树入栈stack
                if (null != node.left)
                {
                    stack.Push(node.left);
                }

                // 如果右子树不为空,则将右子树入栈stack
                if (null != node.right)
                {
                    stack.Push(node.right);
                }
            }

            return resultStack;
        }

至此二叉树后续遍历原理以及实现均已奉上

你可能感兴趣的:(数据结构,二叉树,二叉树遍历,二叉树后序遍历)