单链表的定义以及使用

链表是一种有序的列表,它的内容通常存储与内容分散的位置上。

一般链表的串联方式有两种:

一种是通过数组有序串联链表的列表元素,通常用到两个数组,一个数组存放数据,一个数组存放链接的关系。这种链表的缺点在于,在插于或者删除元素的时候,要频繁的搬动元素,而且数组的大小是固定的,使用缺乏弹性。

另一种则是动态内存配置的链表,它由许多的结点(Node)链接而成,每一个结点包含数据部分以及指向下一个结点的指针(引用)。

我们常说的“链表”一般就是指第二种。

.Net Framework里并没有加入链表的数据结构对象。所以我就自己动手实践了一下。

偶尔看到韩睿的“.NET数据结构对象补遗之单链表”,我没有看他后面的代码部分(他用的是VB.NET),我也来写一个单链表的类。

上面讲了,链表由许多个结点链接而成,那首先,我们要考虑的就是创建一个链表结点的类。

首先,一个结点应该有两个域,一个域用来存放数据,一个域则存放指向下一个结点的引用。

1 /**/ ///<summary>
2///结点对象的类。
3///</summary>

4 public class ListNode
5 {
6Field#regionField
7privateListNode_nextNode;
8privateobject_data;
9#endregion

10
11Property#regionProperty
12/**////<summary>
13///指向下一个结点的引用。
14///</summary>

15publicListNodeNextNode
16{
17get{returnthis._nextNode;}
18set{this._nextNode=value;}
19}

20
21/**////<summary>
22///结点的数据项
23///</summary>

24publicobjectData
25{
26get{returnthis._data;}
27set{this._data=value;}
28}

29#endregion

30
31Constructor#regionConstructor
32/**////<summary>
33///初始化一个结点。
34///</summary>
35///<paramname="data">结点数据项。</param>
36///<paramname="nextNode">指向下一个结点的引用。</param>

37publicListNode(objectdata,ListNodenextNode)
38{
39this._data=data;
40this._nextNode=nextNode;
41}

42
43/**////<summary>
44///初始化一个作为尾结点的结点。
45///</summary>
46///<paramname="data">结点数据项。</param>

47publicListNode(objectdata):this(data,null)
48{
49}

50#endregion

51}


接下来,要考虑的就是创建一个链表类。先考虑一下链表类需要提供哪些操作。

首先,通过位置(索引)获取到对链表中的数据的访问,这对于列表数据结构而言是基本的实现内容,同样,针对链表元素的数据项的所在位置的索引,也是我们需要提供的实现方法之一。

昨天写了篇数组的东西,里面就说到数组的增、删、排效率很低,因为要频繁移动存储位置。而链表作为一种动态内存分配的列表数据结构,在添加、删除、排序方面没有了数组的先天不足,所以添加、删除、排序这几个方法肯定需要在我的这个链表类中得以实现。

从上面这些我首先想到的就是链表类可以从IList继承而来,IList是所有列表对象的抽象基类,也就是所有的列表对象都实现了System.Collections.IList这个接口。除了排序,上面提到的需要实现的方法在IList中都有定义。

同时在这里,我把刚才前面定义的那个结点类作为Nested Class内嵌在链表内中,提升这个结构的聚合性。

1 using System.Collections;
2
3 public class SingleLinkedList:IList
4 {
5publicclassListNode
6{
7//.
8}

9}

在开始为链表类的方法作具体实现之前,先定义几个基本的成员;
1 /**/ ///<summary>
2///链表的头结点。
3///</summary>
4 protected ListNode_head;
5
6 /**/ ///<summary>
7///链表的尾结点。
8///</summary>

9 protected ListNode_tail ;
10
11 /**/ ///<summary>
12///链表结点的数量。
13///</summary>

14 protected int _nodeCount = 0 ;

以及一些基本的内部调用,比如验证结点的有效性,根据结点索引或数据内容查找结点等。
1 /**/ ///<summary>
2///判断指定索引是否超出链表结点索引上下限。
3///</summary>
4///<paramname="index">结点的索引值。</param>

5 protected virtual void Validate( int index)
6 {
7if(index<0||index>=this._nodeCount)
8{
9thrownewArgumentOutOfRangeException("索引越界");
10}

11}

12
13 /**/ ///<summary>
14///判断结点值是否有效。
15///</summary>
16///<paramname="value">结点的值。</param>

17 protected virtual void Validate( object value)
18 {
19if(value==null)
20{
21thrownewArgumentNullException();
22}

23}

24
25 /**/ ///<summary>
26///判断结点的索引以及值是否有效。
27///</summary>
28///<paramname="index">结点的索引值。</param>
29///<paramname="value">结点的值。</param>

30 protected virtual void Validate( int index, object value)
31 {
32this.Validate(index);
33this.Validate(value);
34}

35
36 /**/ ///<summary>
37///通过结点索引查找结点对象。
38///</summary>
39///<paramname="index">结点的索引值。</param>
40///<returns>如果找到指定索引的结点,则返回该结点对象,否则返回null。</returns>

41 public virtual ListNodeFindByIndex( int index)
42 {
43inttmpIndex=0;
44
45//从首结点的下一个结点开始查找
46ListNodecurrent=this._head.NextNode;
47
48ListNodereturnValue=null;
49
50do
51{
52if(tmpIndex==index)
53{
54returnValue=current;
55}

56else
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值