一、 泛型简介
泛型(Generic)是C# 2.0新增的概念之一,其宗旨是避免进行强制类型转换的需求,提高类型安全性,减少需要的装箱量并且让程序员更轻松地创建泛型化的类和方法。泛型类和方法接受所谓的“类型参数”,由它们确定要操作的对象的类型。
二、 问题的提出
.NET框架2.0通过System.Collections.Generic命名空间提供了许多集合类和接口的泛型版本。
.NET框架类库已经包含了大量现成的泛型类。当然,用户也可以根据自己的需要定制泛型类。不知何原因,微软恰好在System.Collections.Generic命名空间中遗漏了二叉树类。须知,二叉树是一种非常有用的数据结构,可用它实现大量的操作,其中包括以极快的速度来排序和搜索数据。
在本文中,我们将使用.NET 2.0泛型概念构造一棵基本的二叉树,使其能容纳多种类型的数据。
三、 使用泛型构造二叉树类实例
由于二叉树类在许多程序中都能用到;所以,最好我们把它做成一个类库以便重用。然后,可以到处重用这个类,而无需复制源代码并重新编译它。
【提示】在.NET中,类库是一系列已经编译的类的集合,所有这些类都存储在一个程序集中。程序集是一个通常采用.dll扩展名的文件。其它项目和应用程序可以添加对程序集的一个引用,然后使用using语句,将它的命名空间带入自己的范围中,从而利用类库中的内容。
启动Visual Studio 2005。选用“类库”模板来创建一个新的Visual C#项目,并将项目命名为BinaryTree。然后,在解决方案资源管理器中,将文件名Class1.cs改变为Tree.cs。
接下来,对Class1类的定义作如下修改,最后代码如下所示:
namespace
BinaryTree ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
...
{
public class Tree<T> where T : IComparable<T> ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
private T data;
private Tree<T> left;
private Tree<T> right;
//……
//
此方法在二叉树中插入一个值为T的结点。
//
注意,因为用户可以使用构造器在树中插入初始的根结点,所以在此方法中
//
我们树是非空的。
public
void
Insert(T newItem) ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
...
{
T currentNodeValue = this.NodeData;
// CompareTo含义上面已作解释,用于判断当前节点值是否大于新项
if (currentNodeValue.CompareTo(newItem) > 0) ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
if (this.LeftTree == null) ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.LeftTree = new Tree<T>(newItem);
}
else ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.LeftTree.Insert(newItem);
}
}
else ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
if (this.RightTree == null) ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.RightTree = new Tree<T>(newItem);
}
else ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.RightTree.Insert(newItem);
}
}
}
//
此方法负责遍历二叉树-把结点值转换为字符串,并输出到控制台
public
void
WalkTree() ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
...
{
if (this.LeftTree != null) //判断左结点是否为空 ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.LeftTree.WalkTree();//非空,则递归遍历左子树
}
Console.WriteLine(this.NodeData.ToString());//输出到控制台
if (this.RightTree != null) //判断右结点是否为空 ![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
...{
this.RightTree.WalkTree();//非空,则递归遍历右子树
}
}
泛型(Generic)是C# 2.0新增的概念之一,其宗旨是避免进行强制类型转换的需求,提高类型安全性,减少需要的装箱量并且让程序员更轻松地创建泛型化的类和方法。泛型类和方法接受所谓的“类型参数”,由它们确定要操作的对象的类型。
二、 问题的提出
.NET框架2.0通过System.Collections.Generic命名空间提供了许多集合类和接口的泛型版本。
.NET框架类库已经包含了大量现成的泛型类。当然,用户也可以根据自己的需要定制泛型类。不知何原因,微软恰好在System.Collections.Generic命名空间中遗漏了二叉树类。须知,二叉树是一种非常有用的数据结构,可用它实现大量的操作,其中包括以极快的速度来排序和搜索数据。
在本文中,我们将使用.NET 2.0泛型概念构造一棵基本的二叉树,使其能容纳多种类型的数据。
三、 使用泛型构造二叉树类实例
由于二叉树类在许多程序中都能用到;所以,最好我们把它做成一个类库以便重用。然后,可以到处重用这个类,而无需复制源代码并重新编译它。
【提示】在.NET中,类库是一系列已经编译的类的集合,所有这些类都存储在一个程序集中。程序集是一个通常采用.dll扩展名的文件。其它项目和应用程序可以添加对程序集的一个引用,然后使用using语句,将它的命名空间带入自己的范围中,从而利用类库中的内容。
启动Visual Studio 2005。选用“类库”模板来创建一个新的Visual C#项目,并将项目命名为BinaryTree。然后,在解决方案资源管理器中,将文件名Class1.cs改变为Tree.cs。
接下来,对Class1类的定义作如下修改,最后代码如下所示:
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
【提示】泛型和约束常常是联系在一起使用的。通过约束,可以将一个泛型类的类型参数限制成实现了一系列特定接口的类型(所以它们能够提供由那些接口定义的方法)。
在本例中,我们修改Tree<T>类的定义,指定类型参数T必须是实现了泛型IComparable<T>接口的一个类型。
【提示】如果我们需要创建一个类,要求它能够根据某种排序方式对值进行比较,那就要实现IComparable接口。此接口包含一个CompareTo方法,由它来获得单个参数,并返回一个整数以指出比较结果。
在本例中,我们修改Tree<T>类的定义,指定类型参数T必须是实现了泛型IComparable<T>接口的一个类型。
【提示】如果我们需要创建一个类,要求它能够根据某种排序方式对值进行比较,那就要实现IComparable接口。此接口包含一个CompareTo方法,由它来获得单个参数,并返回一个整数以指出比较结果。
在上面的Tree<T>类中添加了三个私有变量,只要有二叉树概念,其含义自明,不多赘述。接下来,我们在类中添加两个方法Insert和WalkTree,分别用于插入结点和遍历二叉树。相应代码如下:
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ContractedSubBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/InBlock.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://219.232.114.72/Images/OutliningIndicators/None.gif)
四、 测试Tree<T>类
为了测试上面库中的二叉树类,选择“文件→新建→添加项目”,选用“控制台应用程序”模板来添加一个新项目,并将项目命名为BinaryTreeTest。
在解决方案资源管理器中,选择BinaryTreeTest项目并将之设置为启动项目。
选择“项目→添加引用”。单击“项目”标签,单击BinaryTree项目,并确定。
最后,我们在Main方法中加入如下语句进行测试:
为了测试上面库中的二叉树类,选择“文件→新建→添加项目”,选用“控制台应用程序”模板来添加一个新项目,并将项目命名为BinaryTreeTest。
在解决方案资源管理器中,选择BinaryTreeTest项目并将之设置为启动项目。
选择“项目→添加引用”。单击“项目”标签,单击BinaryTree项目,并确定。
最后,我们在Main方法中加入如下语句进行测试:
static
void
Main(
string
[] args) { Tree
<
int
>
tree1
=
new
Tree
<
int
>
(
10
); tree1.Insert(
9
); tree1.Insert(
6
); tree1.Insert(
5
); tree1.Insert(
-
12
); tree1.Insert(
177
); tree1.Insert(
0
); tree1.Insert(
9
); tree1.Insert(
9
); tree1.WalkTree(); Tree
<
string
>
tree2
=
new
Tree
<
string
>
(
"
Hello
"
); tree2.Insert(
"
World
"
); tree2.Insert(
"
How
"
); tree2.Insert(
"
Old
"
); tree2.Insert(
"
Are
"
); tree2.Insert(
"
You
"
); tree2.WalkTree(); Console.Read(); }
运行结果如下图所示:
五、 小结
“泛型”概念在增加类型安全的同时,也大大提高了软件的模块化开发。在本文中,我们基于泛型概念创建了一棵简单的二叉树。当然,在实践中还有待于大量的“美化”。
![](https://i-blog.csdnimg.cn/blog_migrate/362d6443c8627610734f9095de0c224a.jpeg)
五、 小结
“泛型”概念在增加类型安全的同时,也大大提高了软件的模块化开发。在本文中,我们基于泛型概念创建了一棵简单的二叉树。当然,在实践中还有待于大量的“美化”。