二叉树的遍历
二叉树的遍历,分为深度遍历和广度遍历,其中深度遍历又分为先序、中序和后序。
二叉树的遍历用递归实现,代码形式简单,但是递归借助程序建立起深度遍历的模型显得相对抽象,故而下面的代码会设计深度遍历的非递归实现。
/// <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,