数据结构-单链表

简单单链表

涉及知识点:

  1. 接口IEnumerable<T>,IEnumerator<T>, ICollection<T>,IEquatable<T>
  2. 泛型where使用
  3. 索引器

先上代码( //-_- )

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace SingleLinkedList
 8 {
 9     /// <summary>
10     /// 单链表节点对象
11     /// </summary>
12     public class NodeObj<T>
13         where T : IEquatable<T>
14     {
15         //下一个节点
16         public NodeObj<T> nextNode;
17 
18         //节点值
19         public T value;
20 
21         /// <summary>
22         /// 构造一个节点
23         /// </summary>
24         /// <param name="value">头对象的值</param>
25         public NodeObj(T value)
26         {
27             this.value = value;
28         }
29     }
30 }
链表节点
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace SingleLinkedList
  8 {
  9     /// <summary>
 10     /// 单链表
 11     /// </summary>
 12     /// <typeparam name="T"></typeparam>
 13     public class SingleLinkedList<T> : IEnumerable<T>, ICollection<T>
 14         where T : IEquatable<T>
 15     {
 16         //头节点
 17         private NodeObj<T> headNode;
 18 
 19         #region  构造函数
 20         /// <summary>
 21         /// 构造一个空的单链表
 22         /// </summary>
 23         public SingleLinkedList() { }
 24 
 25         /// <summary>
 26         /// 构造一个指定头的单链表
 27         /// </summary>
 28         /// <param name="value">单链表头节点的值</param>
 29         public SingleLinkedList(T value)
 30         {
 31             NodeObj<T> node = new NodeObj<T>(value);
 32             this.headNode = node;
 33         }
 34 
 35         /// <summary>
 36         /// 构造一个指定头的单链表
 37         /// </summary>
 38         /// <param name="value">头节点</param>
 39         public SingleLinkedList(NodeObj<T> node)
 40         {
 41             this.headNode = node;
 42         }
 43         #endregion
 44 
 45         //索引器
 46         public T this[int index]
 47         {
 48             get { return GetNodeByIndex(index).value; }
 49         }
 50 
 51         /// <summary>
 52         /// 通过索引取得节点
 53         /// </summary>
 54         /// <param name="index">索引,从0开始</param>
 55         /// <returns></returns>
 56         public NodeObj<T> GetNodeByIndex(int index)
 57         {
 58             //初始索引
 59             int i = 0;
 60             //总长度
 61             int count = this.Count;
 62             //索引超出集合范围
 63             if (index < 0 || index > count)
 64             {
 65                 throw new Exception("索引超出集合范围");
 66             }
 67 
 68             NodeObj<T> node = headNode;
 69             while (node != null)
 70             {
 71                 if (i == index)
 72                 {
 73                     return node;
 74                 }
 75                 node = node.nextNode;
 76                 i++;
 77             }
 78 
 79             return null;
 80         }
 81 
 82         /// <summary>
 83         /// 找到值在集合中首次出现的位子
 84         /// </summary>
 85         /// <param name="item"></param>
 86         /// <returns>集合所在索引,未找到返回-1</returns>
 87         public int GetFirstIndex(T item)
 88         {
 89             int index = -1;
 90             for (int i = 0; i < this.Count; i++)
 91             {
 92                 if (GetNodeByIndex(i).value.Equals(item))
 93                 {
 94                     index = i;
 95                     break;
 96                 }
 97             }
 98 
 99             return index;
100         }
101 
102         /// <summary>
103         /// 找到值在集合中最后一次出现的位子
104         /// </summary>
105         /// <param name="item"></param>
106         /// <returns>集合所在索引,未找到返回-1</returns>
107         public int GetLastIndex(T item)
108         {
109             int index = -1;
110             for (int i = this.Count - 1; i >= 0; i--)
111             {
112                 if (GetNodeByIndex(i).value.Equals(item))
113                 {
114                     index = i;
115                     break;
116                 }
117             }
118 
119             return index;
120         }
121 
122 
123         #region 实现接口IEnumerable
124         IEnumerator<T> IEnumerable<T>.GetEnumerator()
125         {
126             return new SingleLinkedListEnumerator(this);
127         }
128 
129         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
130         {
131             return new SingleLinkedListEnumerator(this);
132         }
133         #endregion
134 
135         #region 实现接口ICollection
136 
137         public int Count
138         {
139             get
140             {
141                 int count = 0;
142 
143                 NodeObj<T> node = headNode;
144                 while (node != null)
145                 {
146                     node = node.nextNode;
147                     count++;
148                 }
149                 return count;
150             }
151         }
152 
153         bool ICollection<T>.IsReadOnly
154         {
155             get { return false; }
156         }
157 
158         public void Add(T item)
159         {
160             NodeObj<T> node = new NodeObj<T>(item);
161             //根节点为空
162             if (this.headNode == null)
163             {
164                 this.headNode = node;
165                 return;
166             }
167 
168             NodeObj<T> lastNode = headNode;
169             while (node.nextNode != null)
170             {
171                 node = node.nextNode;
172             }
173             lastNode.nextNode = node;
174 
175         }
176 
177         public void Clear()
178         {
179             this.headNode = null;
180         }
181 
182         public bool Contains(T item)
183         {
184             NodeObj<T> node = headNode;
185             while (node != null)
186             {
187                 if (node.value.Equals(item))
188                 {
189                     return true;
190                 }
191                 node = node.nextNode;
192             }
193             return false;
194         }
195 
196         public void CopyTo(T[] array, int arrayIndex)
197         {
198             try
199             {
200                 NodeObj<T> node = headNode;
201                 int index = arrayIndex;
202                 while (node != null)
203                 {
204                     array[index] = node.value;
205                     node = node.nextNode;
206                 }
207             }
208             catch (Exception e)
209             {
210                 throw e;
211             }
212         }
213 
214         public bool Remove(T item)
215         {
216             bool result = false;
217 
218             NodeObj<T> node = headNode;
219             while (node != null)
220             {
221                 //下一个节点匹配
222                 if (node.nextNode.value.Equals(item))
223                 {
224 
225                     if (node.nextNode.nextNode != null)
226                     {
227                         //下一个节点 还存在 下一个节点
228                         node.nextNode = node.nextNode.nextNode;
229                     }
230                     else
231                     {
232                         //下一个节点 不存在 下一个节点
233                         node.nextNode = null;
234                     }
235                     result = true;
236                 }
237                 node = node.nextNode;
238             }
239 
240             return result;
241         }
242 
243         #endregion
244 
245         public struct SingleLinkedListEnumerator : IEnumerator<T>
246         {
247             //集合
248             private SingleLinkedList<T> obj;
249 
250             //开始索引
251             private int index;
252 
253             /// <summary>
254             /// 构造一个单链表的枚举对象
255             /// </summary>
256             /// <param name="obj"></param>
257             public SingleLinkedListEnumerator(SingleLinkedList<T> obj)
258             {
259                 this.obj = obj;
260                 this.index = -1;
261             }
262 
263             /// <summary>
264             /// 集合当前元素
265             /// </summary>
266             public T Current
267             {
268                 get { return obj[this.index]; }
269             }
270 
271             /// <summary>
272             /// 释放
273             /// </summary>
274             public void Dispose()
275             {
276                 this.obj = null;
277             }
278 
279             /// <summary>
280             /// 指向到下一个元素
281             /// </summary>
282             /// <returns></returns>
283             public bool MoveNext()
284             {
285                 if (index < obj.Count-1)
286                 {
287                     this.index++;
288                     return true;
289                 }
290                 else
291                 {
292                     return false;
293                 }
294             }
295 
296             /// <summary>
297             /// 重置指向
298             /// </summary>
299             public void Reset()
300             {
301                 index = -1;
302             }
303 
304             object System.Collections.IEnumerator.Current
305             {
306                 get { return obj[this.index]; }
307             }
308         }
309 
310     }
311 }
链表

自定义集合支持foreach

foreach会调用对象的GetEnumerator()方法,该方法需要返回IEnumerator对象(这里没有强制要求继承IEnumerable,只要有GetEnumerator方法即可)

  1. IEnumerable 公开枚举数,只有一个方法GetEnumerator(),返回一个IEnumerator对象,IEnumerable<T>是对应的泛型版本
  2. IEnumerator有一个属性(Current集合当前元素),2个方法(MoveNext移动到集合下一个元素,Reset重置指向),IEnumerator<T> 是对应泛型版本,同时继承了IDisposable(定义一种释放资源的方法)

 ICollection<T>接口

该接口用于统一对泛型集合的操作,这样是其他人用自定义集合就像使用c#中的其他集合一样方便

 

IEquatable<T>

同时还有 IComparable<T>,IComparer<T>

官方的描述是IEquatable :指示当前对象是否等于同一类型的另一个对象。

      IComparer:比较两个对象并返回一个值,指示一个对象是小于、等于还是大于另一个对象。

      IComparable:定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。

第一个用来比较2个对象是否相等,第二个用来比较大小,第三个用来排序,但是个人感觉第二个和第三个实际用起来基本没差别

 

泛型where使用

在泛型中使用where限制类型 T 的范围

 

索引器

使用索引器,可以像访问数组一样使用索引访问集合中元素,索引器的索引数据类型可自定

 

 

这里实现了一个非常简单的单链表,c#提供了双链表可供使用 System.Collections.Generic.LinkedList<T>

 

 

 

 

 

    

posted @ 2017-08-28 20:38  小小鱼、  阅读(164)  评论(0编辑  收藏  举报