二叉树中序遍历

二叉树中序遍历

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

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

如上二叉树中序遍历结果为:1 2 3 4 5 6 7 8 9
一件很巧合的事情,遍历结果为一组已排序的序列,熟悉二叉搜索树的同学会发现,上边的二叉树其实是符合搜索二叉树。
二叉搜索树特征如下:
1.每个节点的值大于其左子树上所有节点的值(如果左子树不为空)
2.每个节点的值小于其右子树上所有节点的值(如果右子树不为空)
3.所有左子树和右子树自身也必须是二叉搜索树

检查如上二叉树结构,完全符合二叉树的所有特征,所以可以判定如上二叉树是一颗二叉搜索树。当把二叉树所有节点从左到右依次映射到一个序列中,所得到的序列即为一个按照升序排列的序列。
可以使用此方法来验证一颗二叉树,是否是一个二叉搜索树。

所以一切巧合皆有因果,那么如何来实现验证二叉搜索树的算法呢,没错就是本片文章所将的 二叉搜索树中序遍历

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

2.节点1没有子节点,所以节点2的左子树上所有节点(1)已访问,则回溯访问节点1 的父节点2

3.接着访问节点2的右子树节点3

4.此时节点4的左子树上所有节点(1, 2, 3) 都已访问,则从节点2回溯访问其父节点4

5.接着访问节点4的右子树节点5

6.此时节点6的左子树上所有节点(1, 2, 3, 4, 5) 都已访问,则从节点4回溯访问其父节点6

7.节点6左子树已访问结束,开始访问节点6的右子树,拿到节点8但是不访问,而是要从节点8通过递归或者迭代,得到其最深的左子树节点7,访问节点7

8.节点7没有子节点,所以节点8的左子树上所有节点(7)已访问,则从节点7回溯访问其父节点8

9.接着访问节点8的右子树节点9

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

先序遍历的两种实现:地柜实现、迭代试下

    // 节点定义如下
    public class TreeNode
    {
        public int val;
        public TreeNode left;
        public TreeNode right;
        public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null)
        {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

递归实现如下

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

        public void InorderTraversal(TreeNode node, IList<int> list)
        {
            if (null == node)
            {
                return;
            }

            // 递归调用左子树
            InorderTraversal(node.left, list);

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

            // 递归访问右子树
            InorderTraversal(node.right, list);
        }

迭代实现如下

//迭代实现
        public IList<int> InorderTraversal2(TreeNode root)
        {
            // 集合存储访问节点的值
            IList<int> list = new List<int>();

            // 以栈结构(先进后出)来构建节点访问次序
            Stack<TreeNode> stack = new Stack<TreeNode>();

            // 先将跟节点入栈
            stack.Push(root);

            // 新建临时节点从 root 开始
            TreeNode node = root;
            while (stack.Count > 0)
            {
                // 迭代直到得到最深的左子树
                while (null != node && (null != node.left))
                {
                    stack.Push(node.left);
                    node = node.left;
                }

                // 节点出栈
                node = stack.Pop();
                if (null != node)
                {
                    // 将节点的值存入集合中
                    list.Add(node.val);

                    // 如果有子树不为空,则将右子树入栈
                    if (null != node.right)
                    {
                        stack.Push(node.right);
                    }
                    // 令节点等于其右子树,此时右子树可以为空
                    node = node.right;
                }
            }

            return list;
        }

至此二叉树中序遍历的原理以及实现均已奉上

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