C#实现单向线性链表的设计与实现

顺序表是在计算机内存中用一组地址连续的存储单元依次存储数据元素的线性结构。简单,就不做过多说明了。

单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。在我设计的单向链表类(LinkList类)中,是以LNode类的一个对象来实现链表头。对链表的操作,都将链表头送入LinkList类。因此LinkList类中所有方法都是静态的。而对一个表的传输只需要传递表头就可以了。

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

至于循环单向链表和循环双向链表都是之需要把尾元素指向首元素,在以上2个类实现的基础上再实现也不难。

暂时只写了单向链表类与双向链表节点类,其他的以后有时间慢慢搞了。。。

作者:长沙理工大学 02级 张宇洋
最后修改日期:2006-01-25

  1/* 说明:
  2 * 双向链表的实现很简单,只是需要在结构中再加上个 public LNode Prev;
  3 * 循环链表把最后一个元素的指向第一个元素就好了。可以重新设计一个循环链表头,记录尾对象
  4 * C# 中并不是没指针,不过用了指针其实违背了 C# 的设计初衷,所以程序中并不存在指针
  5 * 关于这个结构是什么样子,可以在运行程序后,从局部变量窗口中查看 L 的的变化
  6 * 从降低算法的复杂度考虑,才会简写了 NextElem() 函数,要不别的函数能方便的从基函数得到扩展
  7 */

  8
  9using System;
 10
 11namespace GyAngle.ZhangYuYang.LinearList
 12{
 13    //Compare() 是数据元素判定函数
 14    public delegate bool CompareLNode(LNode obj1,LNode obj2);
 15    //Visit() 是元素依次访问的函数
 16    public delegate bool VisitLNode(int i,LNode obj);
 17    
 18    /*============================================================
 19    数据存储结构的定义
 20    ============================================================*/

 21
 22    //线性表的单链表储存结构以及头结构
 23    public sealed class LNode
 24    {
 25        public object Data;    //保存数据
 26        public LNode Next;    //保存下一元素对象的引用
 27
 28        public LNode(){}
 29
 30        public LNode(object obj)
 31        {
 32            this.Data=obj;
 33        }

 34
 35        public override string ToString()
 36        {
 37            return this.Data.ToString ();
 38        }

 39
 40        //返回指定对象
 41        public LNode this[int i]
 42        {
 43            get
 44            {
 45                return LinkList.GetElem(this,i);
 46            }

 47        }

 48    }

 49
 50
 51    //线性表的双向链表储存结构
 52    public sealed class DuLNode
 53    {
 54        public DuLNode Prev;    //保存上一元素对象的引用
 55        public object Data;    //保存数据
 56        public DuLNode Next;    //保存下一元素对象的引用
 57
 58        public DuLNode(){}
 59
 60        public DuLNode(object obj)
 61        {
 62            this.Data=obj;
 63        }

 64
 65        public override string ToString()
 66        {
 67            return this.Data.ToString ();
 68        }

 69    }

 70
 71
 72    /============================================================
 73    对应结构的操作
 74    ============================================================*/
 75
 76    //对线性表的单链表的基本操作
 77    public sealed class LinkList
 78    {
 79
 80        //构造函数
 81        private LinkList(){}
 82
 83        //构造一个空的线性表,并且返回这个表的表头
 84        public static LNode InitList()
 85        {
 86            return new LNode(0);    //链性线性表元素头,并且在 Data 字段中记录下元素数目(这个是个优化)
 87        }

 88
 89
 90        //销毁线性表
 91        public static void DestroyList(ref LNode L)
 92        {
 93            L=null;
 94        }

 95
 96
 97        //将表设置为空表
 98        public static void ClearList(ref LNode L)
 99        {
100            L.Data=0;
101            L.Next=null;
102        }

103    
104
105        //若 L 表为空表,则返回 True ,或则返回 False
106        public static bool ListEmpty(ref LNode L)
107        {
108            if(0==(int)L.Data)return true;else return false;
109        }

110
111
112        //返回 L 中数据元素个数
113        public static int ListLength(LNode L)
114        {
115            return (int)L.Data;
116        }

117
118
119        //返回链性线性表中的一个指定值
120        public static LNode GetElem(LNode L,int p)
121        {
122            if(p>ListLength(L)||p<0)throw new ArgumentOutOfRangeException("p","指向了不存在的对象。"+"p="+p);
123            LNode obj=L;
124            for(int i=0;i<p;i++)
125            {
126                obj=NextElem(obj);
127            }

128            return obj;
129        }

130
131
132        //返回 L 中第一个与 e 满足关系 func() 的数据元素的位序,若这样的元素不存在,则返回 0
133        public static int LocateElem(LNode L,LNode e,CompareLNode func)
134        {
135            int i=0;
136            LNode obj=L;
137            for(i=0;i<ListLength(L);i++)
138            {
139                obj=NextElem(obj);
140                if(true==func(obj,e))
141                {
142                    return i+1;
143                }

144            }

145            return 0;
146        }

147
148        /*============================================================
149        按道理说,这2个函数要求应该更严格些,实现起来并不难,不过这样更简便点,而且够用了
150        NextElem() 函数完整版以给出,不过那样的话 LocateElem() 函数的使用又会不方便
151        ============================================================*/

152        //若元素 cur_e 是 L 的数据元素,且不是第一个,则返回它的前驱,否则返回 null
153        public static LNode PriorElem(LNode L,LNode cur_e)
154        {
155            int i=LocateElem(L,cur_e,new CompareLNode(CompareElement));
156            if(2>i)
157            {
158                return null;
159            }

160            return GetElem(L,i-1);
161        }

162
163
164        /*若元素 cur_e 是 L 的数据元素,且不是最后一个,则返回它的后继,否则返回 null
165        public static LNode NextElem(LNode L,LNode cur_e)
166        {
167            int i=LocateElem(L,cur_e);
168            if(0==i||ListLength(L)==i)
169            {
170                return null;
171            }
172            return cur_e.Next;
173        }*/

174
175
176        /*返回元素 cur_e 的下一个元素,简单版 NextElem 函数。*/
177        public static LNode NextElem(LNode cur_e)
178        {
179            return cur_e.Next;
180        }

181
182
183        //在L中的第 p 个元素处插入新元素 e
184        public static void ListInsert(LNode L,int p,object e)
185        {
186            if(p>ListLength(L)||p<0)throw new ArgumentOutOfRangeException("p","指向了一个不存在的位置。"+"p="+p);
187            LNode NewElement=new LNode(e);
188            LNode obj=GetElem(L,p);
189            NewElement.Next=obj.Next;
190            obj.Next=NewElement;
191            L.Data=(int)L.Data+1;
192        }

193
194
195        //删除 L 的第 p 个元素
196        public static void ListDelete(LNode L,int p)
197        {
198            if(p>ListLength(L)||p<1)throw new ArgumentOutOfRangeException("p","指向了不存在的对象。"+"p="+p);
199            LNode obj=GetElem(L,p-1);
200            obj.Next=(obj.Next).Next;
201            L.Data=(int)L.Data-1;
202        }

203
204
205        //依次对 L 的每一个元素调用函数 func() 。一旦 func() 失败,则操作失败
206        public static bool ListTraverse(LNode L,VisitLNode func)
207        {
208            LNode obj=L;
209            for(int i=0;i<ListLength(L);i++)
210            {
211                obj=obj.Next;
212                if(false==func(i,obj))return false;
213            }

214            return true;
215        }

216
217
218        //类内部默认的用于定位函数的 func()
219        static bool CompareElement(LNode obj1,LNode obj2)
220        {
221            if(obj1.Data.ToString()==obj2.Data.ToString())return true;else return false;
222        }

223
224        
225    }

226
227
228    
229
230
231
232
233}

 

原文地址:https://www.cnblogs.com/fengye/p/639376.html