











2018-08-21 08:26 蓝之风 阅读(3832) 评论() 收藏 举报
在计算机中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。
二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根节点之后,每个顶点定义了唯一的父节点,和最多2个子节点。然而,没有足够的信息来区分左节点和右节点。
从逻辑上讲二叉树有五种形态,如上图:
遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有节点,使每一个节点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。
设L、D、R分别表示遍历左子树、访问根节点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先序遍历),LDR(称为中序遍历),LRD (称为后序遍历)
首先访问根,再先序遍历左子树,最后先序遍历右子树。如上图遍历的结果是:ABCDE
首先中序遍历左子树,再访问根,最后中序遍历右子树,如上图遍历的结果是:CBDAE
首先后序遍历左子树,再后序遍历右子树,最后访问根。如上图遍历的结果是:CDBEA
public class Node { public Node(int i) { Data = i; } public int Data { get; set; } public Node Left { get; set; } public Node Right { get; set; } public void Display(string lr) { Console.Write(lr + ": " + Data); }
先序遍历
public void DLRDisplay(Node theNode) { if (theNode != null) { theNode.Display("InOrder"); InOrder(theNode.Left); InOrder(theNode.Right); } }
中序遍历
public void LDRDisplay(Node theNode) { if (theNode != null) { InOrder(theNode.Left); theNode.Display("InOrder"); InOrder(theNode.Right); } }
后序遍历
public void LRDDisplay(Node theNode) { if (theNode != null) { InOrder(theNode.Left); InOrder(theNode.Right); theNode.Display("InOrder"); } }
代码实现
public enum Order { DLR,//先序遍历 LDR,//中序遍历 LRD //后序遍历 } public abstract class AbstractTreeNode { protected string name; public AbstractTreeNode(string name) { this.name = name; } public AbstractTreeNode Left { get; set; } public AbstractTreeNode Right { get; set; } public abstract void Display(Order order); } public class TreeNode : AbstractTreeNode { public TreeNode(string name) : base(name) { } public override void Display(Order order) { switch (order) { case Order.DLR:// D->L->R DLRDisplay(order); break; case Order.LDR://L->D->R LDRDisplay(order); break; case Order.LRD://L->R->D LRDDisplay(order); break; } } private void DLRDisplay(Order order) { Console.Write(name); if (Left != null) { Left.Display(order); } if (Right != null) { Right.Display(order); } } private void LDRDisplay(Order order) { if (Left != null) { Left.Display(order); } Console.Write(name); if (Right != null) { Right.Display(order); } } private void LRDDisplay(Order order) { if (Left != null) { Left.Display(order); } if (Right != null) { Right.Display(order); } Console.Write(name); } } public class LeafNode : AbstractTreeNode { public LeafNode(string name) : base(name) { } public override void Display(Order order) { Console.Write(name); } }
测试:
/// <summary> /// A /// / \ /// B E /// / \ /// C D /// </summary> /// <param name="args"></param> static void Main(string[] args) { AbstractTreeNode rootA, b, c, d, e; rootA = new TreeNode("A"); b = new TreeNode("B"); c = new LeafNode("C"); d = new LeafNode("D"); e = new LeafNode("E"); rootA.Left = b; rootA.Right = e; b.Left = c; b.Right = d; rootA.Display(Order.DLR);//output->ABCDE Console.WriteLine(); rootA.Display(Order.LDR);//output->CBDAE Console.WriteLine(); rootA.Display(Order.LRD);//output->CDBEA Console.ReadKey(); }
结果:
先序遍历的结果:ABCDE
中序遍历的结果:CBDAE
后序遍历的结果:CDBEA
在这里其实可以省略掉叶子节点类,只需要一个实现类TreeNode就可以了这样就变得更简单了:
代码中可以删掉LeafNode类,客户端只针对TreeNode实现就可以了。因为这里没有针对复杂的树枝节点的管理操作。因此不需要分别对待树枝节点和叶子节点。
public enum Order { DLR,//先序遍历 LDR,//中序遍历 LRD //后序遍历 } public abstract class AbstractTreeNode { protected string name; public AbstractTreeNode(string name) { this.name = name; } public AbstractTreeNode Left { get; set; } public AbstractTreeNode Right { get; set; } public abstract void Display(Order order); } public class TreeNode : AbstractTreeNode { public TreeNode(string name) : base(name) { } public override void Display(Order order) { switch (order) { case Order.DLR:// D->L->R DLRDisplay(order); break; case Order.LDR://L->D->R LDRDisplay(order); break; case Order.LRD://L->R->D LRDDisplay(order); break; } } private void DLRDisplay(Order order) { Console.Write(name); if (Left != null) { Left.Display(order); } if (Right != null) { Right.Display(order); } } private void LDRDisplay(Order order) { if (Left != null) { Left.Display(order); } Console.Write(name); if (Right != null) { Right.Display(order); } } private void LRDDisplay(Order order) { if (Left != null) { Left.Display(order); } if (Right != null) { Right.Display(order); } Console.Write(name); } }
测试:
/// <summary> /// A /// / \ /// B E /// / \ /// C D /// </summary> /// <param name="args"></param> static void Main(string[] args) { AbstractTreeNode rootA, b, c, d, e; rootA = new TreeNode("A"); b = new TreeNode("B"); c = new TreeNode("C"); d = new TreeNode("D"); e = new TreeNode("E"); rootA.Left = b; rootA.Right = e; b.Left = c; b.Right = d; rootA.Display(Order.DLR);//output->ABCDE Console.WriteLine(); rootA.Display(Order.LDR);//output->CBDAE Console.WriteLine(); rootA.Display(Order.LRD);//output->CDBEA Console.ReadKey(); }
结果:
先序遍历的结果:ABCDE
中序遍历的结果:CBDAE
后序遍历的结果:CDBEA
两次测试的结果是一样的。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。