二叉树的遍历

二叉树的遍历,分为深度遍历和广度遍历,其中深度遍历又分为先序、中序和后序。

二叉树的遍历用递归实现,代码形式简单,但是递归借助程序建立起深度遍历的模型显得相对抽象,故而下面的代码会设计深度遍历的非递归实现。

    /// <summary>
    /// 二叉树
    /// </summary>
    public class BinaryTree
    {
        private Node_BinaryTree _head;
        /// <summary>
        /// 二叉树头节点
        /// </summary>
        public Node_BinaryTree Head
        {
            get { return _head; }
        }

        private List<int> _listDataSource;//二叉树数据源

        /// <summary>
        /// 构造函数,根据数据源构建二叉树
        /// </summary>
        /// <param name="listDataSource"></param>
        public BinaryTree(List<int> listDataSource)
        {
            _head = new Node_BinaryTree();
            _listDataSource = listDataSource;
            AddNode(_head, 0);
        }

        /// <summary>
        /// 重建二叉树
        /// </summary>
        private void ReBuildBinaryTree()
        {
            _head = new Node_BinaryTree();
            AddNode(_head, 0);
        }

        /// <summary>
        /// 添加子节点方法
        /// </summary>
        /// <param name="node"></param>
        /// <param name="indexDataSource"></param>
        private void AddNode(Node_BinaryTree node, int indexDataSource)
        {
            node.NodeValue = _listDataSource[indexDataSource];
            //查看左节点
            int indexLeftChild = (indexDataSource + 1) * 2 - 1;
            if (indexLeftChild >= _listDataSource.Count)
                return;
            node.LeftChild = new Node_BinaryTree();
            node.LeftChild.Parent = node;
            AddNode(node.LeftChild, indexLeftChild);

            //查看右节点
            int indexRightChild = (indexDataSource + 1) * 2;
            if (indexRightChild >= _listDataSource.Count)
                return;
            node.RightChild = new Node_BinaryTree();
            node.RightChild.Parent = node;
            AddNode(node.RightChild, indexRightChild);
        }

        /// <summary>
        /// 先序遍历,递归
        /// </summary>
        /// <param name="node"></param>
        public void PreOrder_Recursion(Node_BinaryTree node)
        {
            if (node == null)
                return;
            VisitNode(node);
            PreOrder_Recursion(node.LeftChild);
            PreOrder_Recursion(node.RightChild);
        }

        /// <summary>
        /// 先序遍历,非递归操作,用栈代替 
        /// </summary>
        public void PreOrder_Stack1()
        {
            Stack<Node_BinaryTree> stack = new Stack<Node_BinaryTree>();
            Node_BinaryTree nodeTemp = _head;
            do
            {
                //先访问节点,先序遍历体现在这里
                VisitNode(nodeTemp);

                //右子节点入栈,用栈来记忆以便回溯
                if (nodeTemp.RightChild != null)
                {
                    stack.Push(nodeTemp.RightChild);
                }

                //依次访问左节点
                if (nodeTemp.LeftChild != null)
                {
                    nodeTemp = nodeTemp.LeftChild;
                }
                else
                {
                    //弹出压入的右节点
                    if (stack.Count != 0)
                        nodeTemp = stack.Pop();
                    else
                        nodeTemp = null;
                }
            } while (stack.Count != 0 || nodeTemp != null);
        }

        /// <summary>
        /// 先序遍历,非递归操作,用栈代替 
        /// </summary> 
        public void PreOrder_Stack2()
        {
            //建栈
            Stack<Node_BinaryTree> stack = new Stack<Node_BinaryTree>();
            stack.Push(_head);
            while (stack.Count != 0)
            {
                Node_BinaryTree nodeTemp = stack.Pop();
                //先访问
                VisitNode(nodeTemp);
                //压入右子节点
                if (nodeTemp.RightChild != null)
                    stack.Push(nodeTemp.RightChild);
                //压入左子节点
                if (nodeTemp.LeftChild != null)
                    stack.Push(nodeTemp.LeftChild);
            }
        }

        /// <summary>
        /// 先序遍历,非递归操作,用回溯法,不用栈结构
        /// </summary>
        public void PreOrder_BackTrace() 
        {
            //重建二叉树
            ReBuildBinaryTree();

            Node_BinaryTree nodeTemp = _head;
            while (nodeTemp != null)
            {
                //访问节点
                if (nodeTemp.IsVisited == false)
                {
                    VisitNode(nodeTemp);
                    nodeTemp.IsVisited = true;
                }

                if (nodeTemp.LeftChild != null && nodeTemp.LeftChild.IsVisited == false) //访问左节点
                {
                    nodeTemp = nodeTemp.LeftChild;
                }
                else
                {
                    if (nodeTemp.RightChild != null && nodeTemp.RightChild.IsVisited == false) //访问右节点
                    {
                        nodeTemp = nodeTemp.RightChild;
                    }
                    else
                    {
                        nodeTemp = nodeTemp.Parent; //回溯至父节点
                    }
                }
            }
        }

        /// <summary>
        /// 中序遍历
        /// </summary>
        /// <param name="node"></param>
        public void InOrder_Recursion(Node_BinaryTree node)
        {
            if (node == null)
                return;
            InOrder_Recursion(node.LeftChild);
            VisitNode(node);
            InOrder_Recursion(node.RightChild);
        }

        /// <summary>
        /// 中序遍历,非递归操作,用栈代替
        /// </summary>
        public void InOrder_Stack()
        {
            Node_BinaryTree nodeTemp = _head;
            Stack<Node_BinaryTree> stack = new Stack<Node_BinaryTree>();

            while (stack.Count != 0 || nodeTemp != null)
            {
                //左子树入栈
                while (nodeTemp != null)
                {
                    stack.Push(nodeTemp);
                    nodeTemp = nodeTemp.LeftChild;
                }

                nodeTemp = null;
                if (stack.Count != 0)
                {
                    nodeTemp = stack.Pop();
                    //访问节点,中序
                    VisitNode(nodeTemp);
                    //处理右子节点
                    nodeTemp = nodeTemp.RightChild;
                }
            }
        }

        /// <summary>
        /// 中序遍历,回溯
        /// </summary>
        public void InOrder_BackTrace()
        {
            //重建二叉树
            ReBuildBinaryTree();

            Node_BinaryTree nodeTemp = _head;
            while (nodeTemp!=null)
            {
                //一直走左分支
                while (nodeTemp.LeftChild != null&&nodeTemp.LeftChild.IsVisited==false)
                {
                    nodeTemp = nodeTemp.LeftChild;
                }

                //访问节点
                if (nodeTemp != null&&nodeTemp.IsVisited==false)
                {
                    VisitNode(nodeTemp);
                    nodeTemp.IsVisited = true;
                }

                //处理右子节点
                if (nodeTemp.RightChild != null&&nodeTemp.RightChild.IsVisited==false)
                {
                    nodeTemp = nodeTemp.RightChild;
                }
                else
                {
                    //回溯至父节点
                    nodeTemp = nodeTemp.Parent;
                }
            }
        }

        /// <summary>
        /// 后序遍历
        /// </summary>
        /// <param name="node"></param>
        public void PostOrder(Node_BinaryTree node)
        {
            if (node == null)
                return;
            PostOrder(node.LeftChild);
            PostOrder(node.RightChild);
            VisitNode(node);
        }

        /// <summary>
        /// 层序遍历
        /// </summary>
        public void LevelOrder()
        {
            Queue<Node_BinaryTree> queue = new Queue<Node_BinaryTree>();
            queue.Enqueue(_head);
            while (queue.Count != 0)
            {
                Node_BinaryTree nodeTemp = queue.Dequeue();
                VisitNode(nodeTemp);
                //左节点入队
                if (nodeTemp.LeftChild != null)
                {
                    queue.Enqueue(nodeTemp.LeftChild);
                }
                //右节点入队
                if (nodeTemp.RightChild != null)
                {
                    queue.Enqueue(nodeTemp.RightChild);
                }
            }
        }

        /// <summary>
        /// 访问节点
        /// </summary>
        /// <param name="node"></param>
        public void VisitNode(Node_BinaryTree node)
        {
            LogCommon.WriteRecord(node.NodeValue.ToString() + "");
        }

        /// <summary>
        /// 测试用
        /// </summary>
        public static void Test()
        {
            List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
            BinaryTree tree = new BinaryTree(list);
            LogCommon.WriteRecord("先序遍历的结果是:\r\n");
            tree.PreOrder_Recursion(tree.Head);
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("先序遍历(栈1)的结果是:\r\n");
            tree.PreOrder_Stack1();
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("先序遍历(栈2)的结果是:\r\n");
            tree.PreOrder_Stack2();
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("先序遍历(回溯)的结果是:\r\n");
            tree.PreOrder_BackTrace();
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("中序遍历的结果是:\r\n");
            tree.InOrder_Recursion(tree.Head);
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("中序遍历(栈)的结果是:\r\n");
            tree.InOrder_Stack();
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("中序遍历(回溯)的结果是:\r\n");
            tree.InOrder_BackTrace();
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("后序遍历的结果是:\r\n");
            tree.PostOrder(tree.Head);
            LogCommon.WriteRecord("\r\n");

            LogCommon.WriteRecord("层序遍历的结果是:\r\n");
            tree.LevelOrder();
            LogCommon.WriteRecord("\r\n");
        }
    }

    /// <summary>
    /// 二叉树节点
    /// </summary>
    public class Node_BinaryTree
    {
        public Node_BinaryTree LeftChild;
        public Node_BinaryTree RightChild;
        public int NodeValue;
        public Node_BinaryTree Parent;
        public bool IsVisited = false;
    }

 程序运行结果:

先序遍历的结果是:
1,2,4,8,9,5,10,11,3,6,7,
先序遍历(栈1)的结果是:
1,2,4,8,9,5,10,11,3,6,7,
先序遍历(栈2)的结果是:
1,2,4,8,9,5,10,11,3,6,7,
先序遍历(回溯)的结果是:
1,2,4,8,9,5,10,11,3,6,7,
中序遍历的结果是:
8,4,9,2,10,5,11,1,6,3,7,
中序遍历(栈)的结果是:
8,4,9,2,10,5,11,1,6,3,7,
中序遍历(回溯)的结果是:
8,4,9,2,10,5,11,1,6,3,7,
后序遍历的结果是:
8,9,4,10,11,5,2,6,7,3,1,
层序遍历的结果是:
1,2,3,4,5,6,7,8,9,10,11,

posted on 2013-02-28 11:28  豆沙包没有肉  阅读(184)  评论(0编辑  收藏  举报

导航