泛型,是指通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。
泛型类型和普通类型的区别在于泛型类型与一组类型参数或类型变量关联。
通常先声明泛型,然后通过类型实例化来使用泛型。定义泛型的语法格式如下:
[访问修饰符][返回类型] 泛型名称<类型参数列表>
其中,“泛型名称”要符合标识符的定义。尖括号表示类型参数列表,可以包含一个或多个类型参数,如
树(Tree)是n(n≥0)个结点的有限集。
它或为空树(n = 0),或为非空树。
对于非空树T:(1)有且仅有一个称之为根的结点;
(2)除根结点以外的其余结点可分为m(m>0)个互不相交的有限集T1, T2, …, Tm, 其中每一个集合本身又是一棵树,并且称为根的子树(SubTree)。
二叉树为m=2,即除根结点以外的其余结点分为两个互不相交的子集T1和T2,分别称为T的左子树和右子树,且T1和T2本身又都是二叉树。
二叉树的结构最简单,规律性最强;
可以证明,所有树都能转为唯一对应的二叉树,不失一般性。
所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。
从二叉树的递归定义可知,一棵非空的二叉树由根结点及左、右子树这三个基本部分组成。因此,在任一给定结点上,可以按某种次序执行三个操作:
⑴访问结点本身(N),
⑵遍历该结点的左子树(L),
⑶遍历该结点的右子树(R)。
以上三种操作有六种执行次序:
NLR、LNR、LRN、NRL、RNL、RLN。
前三种次序与后三种次序对称,故只讨论先左后右的前三种次序。
NLR:前序遍历(Preorder Traversal 亦称(先序遍历))
——访问根结点的操作发生在遍历其左右子树之前。
LNR:中序遍历(Inorder Traversal)
——访问根结点的操作发生在遍历其左右子树之中(间)。
LRN:后序遍历(Postorder Traversal)
——访问根结点的操作发生在遍历其左右子树之后。
除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
using System;
using System.Collections;
using System.Collections.Generic;
定义自定义泛型树Tree类的枚举器
class TreeEnum : IEnumerator
{
public T[] PreNodeList;
int position = -1;//位置字段,初始化为-1
public TreeEnum(T[] ts)//构造函数
{
PreNodeList = ts;
}
public bool MoveNext()//定义TreeEnum的MoveNext方法
{
position++;
return (position < PreNodeList.Length);
}
public void Reset()//定义TreeEnum的Reset方法
{
position = -1;
}
public T Current//定义TreeEnum的Current属性
{
get
{ return PreNodeList[position]; }
}
object IEnumerator.Current//实现IEnumerator的Current属性
{
get
{ return Current; }
}
public void Dispose()
{
throw new NotImplementedException();
}
}
自定义了泛型树Tree类
class Tree : IEnumerable where T : IComparable
以下为类成员及函数
IEnumerator IEnumerable.GetEnumerator()//实现IEnumerable的GetEnumerator方法
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()//实现IEnumerable的GetEnumerator方法
{
return GetEnumerator();
}
public TreeEnum GetEnumerator()//定义Tree类的GetEnumerator()
{
return new TreeEnum(WalkTreeList);
}
public IEnumerable GetWalkList//含yield return语句的GetWalkList属性
{
get
{
for (int i = 0; i < this.GetWalkTreeList.Length; i++)
yield return GetWalkTreeList[i];
}
}
private T NodeData { get; set; }//根结点
private Tree LeftTree { get; set; }//左子树
private Tree RightTree { get; set; }//右子树
public Tree(T NewNode) { NodeData = NewNode; }//含参构造函数
public void Insert(T NewNode)//添加树结点
{
T NodeValue = this.NodeData;
if (NodeValue.CompareTo(NewNode) > 0)// 判断当前节点值是否大于新项
{
if (this.LeftTree == null)
{
this.LeftTree = new Tree(NewNode);
}
else
{
this.LeftTree.Insert(NewNode);
}
}
else
{
if (this.RightTree == null)
{
this.RightTree = new Tree(NewNode);
}
else
{
this.RightTree.Insert(NewNode);
}
}
}
public T[] WalkTreeList = new T[16];//遍历序列数组
public T[] GetWalkTreeList = new T[16];//使用get访问器的遍历序列数组
public int WalkNum = 0;
//进行遍历选择
public void WalkTree(Tree tree, T[] TreeList, int mark, bool New)
{
if (New) { WalkNum = 0; New = false; }
switch (mark)
{
case 1://前序遍历
if (tree == null) return;
TreeList[WalkNum++] = tree.NodeData;
WalkTree(tree.LeftTree, TreeList, mark, New);
WalkTree(tree.RightTree, TreeList, mark, New);
break;
case 2://中序遍历
if (tree == null) return;
WalkTree(tree.LeftTree, TreeList, mark, New);
TreeList[WalkNum++] = tree.NodeData;
WalkTree(tree.RightTree, TreeList, mark, New);
break;
case 3://后序遍历
if (tree == null) return;
WalkTree(tree.LeftTree, TreeList, mark, New);
WalkTree(tree.RightTree, TreeList, mark, New);
TreeList[WalkNum++] = tree.NodeData;
break;
case 4://层序遍历
if (tree == null) return;
//利用队列先进先出进行遍历
Queue> Q = new Queue>();//开辟队列空间
Q.Enqueue(tree);//根结点入队列
while (Q.Count != 0)//队列非空时
{
Tree TheTree = Q.Dequeue();//首元素出队
TreeList[WalkNum++] = TheTree.NodeData;//将该结点的数据记录到数组中
if (TheTree.LeftTree != null) { Q.Enqueue(TheTree.LeftTree); }//左结点入队
if (TheTree.RightTree != null) { Q.Enqueue(TheTree.RightTree); }//右结点入队
}
break;
}
}
class Program
{
static void Main(string[] args)
{
//创建二叉树
Tree tree1 = new Tree(10);
tree1.Insert(3);
tree1.Insert(4);
tree1.Insert(-3);
tree1.Insert(6);
tree1.Insert(8);
tree1.Insert(5);
tree1.Insert(2);
tree1.Insert(14);
tree1.Insert(9);
tree1.Insert(23);
tree1.Insert(41);
tree1.Insert(16);
tree1.Insert(20);
tree1.Insert(0);
tree1.Insert(1);
//用枚举器进行先序遍历
tree1.WalkTree(tree1, tree1.WalkTreeList, 1, true);
Console.Write("用枚举器对自定义泛型树进行先序遍历,结果为:");
foreach (int item in tree1.WalkTreeList)
{
Console.Write(item + " ");
}
Console.Write("\n");
//用get访问器进行中序遍历
tree1.WalkTree(tree1, tree1.GetWalkTreeList, 2, true);
Console.Write("用get访问器对自定义泛型树进行中序遍历,结果为:");
foreach (int item in tree1.GetWalkList)
{
Console.Write(item + " ");
}
Console.Write("\n");
//用get访问器进行后序遍历
tree1.WalkTree(tree1, tree1.GetWalkTreeList, 3, true);
Console.Write("用get访问器对自定义泛型树进行后序遍历,结果为:");
foreach (int item in tree1.GetWalkList)
{
Console.Write(item + " ");
}
Console.Write("\n");
//用get访问器进行层序遍历
tree1.WalkTree(tree1, tree1.GetWalkTreeList, 4, true);
Console.Write("用get访问器对自定义泛型树进行层序遍历,结果为:");
foreach (int item in tree1.GetWalkList)
{
Console.Write(item + " ");
}
Console.Write("\n");
}
}
百度百科:二叉树遍历 https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91%E9%81%8D%E5%8E%86/9796049?fr=aladdin
基于C# 2.0泛型构造一个二叉树类 https://blog.51cto.com/zhuxianzhong/59356
学习C#泛型概述,构建二叉树的泛型类 https://blog.csdn.net/qq_40242160/article/details/104940914?utm_source=app&app_version=4.18.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
感谢阅读!