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

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

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

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

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

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

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

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

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

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

 34InBlock.gif
 35InBlock.gif        public override string ToString()
 36ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 37InBlock.gif            return this.Data.ToString ();
 38ExpandedSubBlockEnd.gif        }

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

 47ExpandedSubBlockEnd.gif        }

 48ExpandedSubBlockEnd.gif    }

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

 64InBlock.gif
 65InBlock.gif        public override string ToString()
 66ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 67InBlock.gif            return this.Data.ToString ();
 68ExpandedSubBlockEnd.gif        }

 69ExpandedSubBlockEnd.gif    }

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

 88InBlock.gif
 89InBlock.gif
 90InBlock.gif        //销毁线性表
 91InBlock.gif        public static void DestroyList(ref LNode L)
 92ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 93InBlock.gif            L=null;
 94ExpandedSubBlockEnd.gif        }

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

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

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

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

128InBlock.gif            return obj;
129ExpandedSubBlockEnd.gif        }

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

144ExpandedSubBlockEnd.gif            }

145InBlock.gif            return 0;
146ExpandedSubBlockEnd.gif        }

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

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

160InBlock.gif            return GetElem(L,i-1);
161ExpandedSubBlockEnd.gif        }

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

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

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

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

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

214InBlock.gif            return true;
215ExpandedSubBlockEnd.gif        }

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

223InBlock.gif
224InBlock.gif        
225ExpandedSubBlockEnd.gif    }

226InBlock.gif
227InBlock.gif
228InBlock.gif    
229InBlock.gif
230InBlock.gif
231InBlock.gif
232InBlock.gif
233ExpandedBlockEnd.gif}

 

转载于:https://www.cnblogs.com/fengye/archive/2007/02/04/639376.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值