//using System;//using System.Collections.Generic;//using System.Text;//using System.Collections;
//public class LinkedListNode//{// public LinkedListNode(Object value)// {// this.value = value;// }
// //结点数据值// private object value;// public object Value// {// get// {// return this.value;// }// }
// //双向结点指向引用// private LinkedListNode next;// private LinkedListNode pre;// public LinkedListNode Next// {// get { return this.next; }// internal set { this.next = value; }// }// public LinkedListNode Pre// {// get { return this.pre; }// internal set { this.pre = value; }// }//}
结点的数据存储在Object类型的Value字段中。下面我们来创建链表类,该链表类有一个头结点、尾结点和在链表的末尾添加/删除结点的方法:
双向链表类//public class LinkedList//{// //头结点// private LinkedListNode head;// public LinkedListNode Head// {// get { return this.head; }// }// //尾结点// private LinkedListNode last;// public LinkedListNode Last// {// get { return this.last; }// }
// //在链表尾插入结点// public LinkedListNode AddNode(Object value)// {// LinkedListNode node = new LinkedListNode(value);
// if (head == null)// {// head = node;// last = head;// }// else// {// last.Next = node;// node.Pre = last;// last = node;// }
// return last;// }
// //在链表尾删除结点// public LinkedListNode SubNode()// {// if (last == null)// {// return null;// }// else// {// LinkedListNode node = last.Pre;// node.Next = null;// last = node;// }
// return last;// }//}
因为是链表,所以我们希望能使用foreach遍历链表,那么,将链表类LinkedList继承IEnumerable接口并实现GetEnumerator()方法:
//using System;//using System.Collections.Generic;using System.;//using System.Text;//using System.Collections;
//namespace ConsoleApplication1//{// //结点类// public class LinkedListNode// { // public LinkedListNode(Object value)// {// this.value = value;// }
// //结点数据值// private object value;// public object Value // {// get // {// return this.value;// }// }
// //双向结点指向引用// private LinkedListNode next;// private LinkedListNode pre;// public LinkedListNode Next // {// get { return this.next; }// internal set { this.next = value; }// }// public LinkedListNode Pre// {// get { return this.pre; }// internal set { this.pre = value; }// }// }
// //双向链表类// public class LinkedList : IEnumerable// {// //头结点// private LinkedListNode head;// public LinkedListNode Head // {// get { return this.head; }// }// //尾结点// private LinkedListNode last;// public LinkedListNode Last// {// get { return this.last; }// }
// //在链表尾插入结点// public LinkedListNode AddNode(Object value) // {// LinkedListNode node = new LinkedListNode(value);
// if (head == null)// {// head = node;// last = head;// }// else// {// last.Next = node;// node.Pre = last;// last = node;// }
// return last;// }
// //在链表尾删除结点// public LinkedListNode SubNode()// {// if (last == null)// {// return null;// }// else// {// LinkedListNode node = last.Pre;// node.Next = null;// last = node;// }
// return last;// }
// #region IEnumerable 成员
// public IEnumerator GetEnumerator()// {// LinkedListNode curr = head;// while (curr != null)// {// yield return curr.Value;// curr = curr.Next;// }// }
// #endregion// }
//}
//这样我们就可以使用链表了,但该链表中的存储数据只能使Object类型的,这就并不能保证链表中的数据是类型统一的,因此在使用foreach遍历链表时可能出现致命的错误。比如该链表中有整形数据和字符串数据。而且,该链表并不能够为我们提供一个标准的模板。
//下面,我们改进LinkedListNode结点类,使其使用泛型——存储数据的类型使我们任意指定的类型:
using System;using System.Collections.Generic;using System.Text;using System.Collections;
namespace LinkedListNode{ public class LinkedListNode<T> { public LinkedListNode(T value) { this.value = value; }
//结点数据值 private T value; public T Value { get { return this.value; } }
//双向结点指向引用 private LinkedListNode<T> next; private LinkedListNode<T> pre; public LinkedListNode<T> Next { get { return this.next; } internal set { this.next = value; } } public LinkedListNode<T> Pre { get { return this.pre; } internal set { this.pre = value; } } }
//同样,也需要将链表类改为泛型类:
public class LinkedList<T> : IEnumerable<T> { //头结点 private LinkedListNode<T> head; public LinkedListNode<T> Head { get { return this.head; } } //尾结点 private LinkedListNode<T> last; public LinkedListNode<T> Last { get { return this.last; } }
//在链表尾插入结点 public LinkedListNode<T> AddNode(T value) { LinkedListNode<T> node = new LinkedListNode<T>(value);
if (head == null) { head = node; last = head; } else { last.Next = node; node.Pre = last; last = node; }
return last; }
//在链表尾删除结点 public LinkedListNode<T> SubNode() { if (last == null) { return null; } else { LinkedListNode<T> node = last.Pre; node.Next = null; last = node; }
return last; }
#region IEnumerable 成员
public IEnumerator<T> GetEnumerator() { LinkedListNode<T> curr = head; while (curr != null) { yield return curr.Value; curr = curr.Next; } }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } class Program { static void Main(string[] args) { LinkedList<int> list2 = new LinkedList<int>(); list2.AddNode(1); list2.AddNode(3); list2.AddNode(5); Console.WriteLine("Before Sub:"); foreach (int i in list2) { Console.WriteLine(i); } Console.WriteLine("After Sub:"); list2.SubNode(); foreach (int i in list2) { Console.WriteLine(i); } Console.ReadLine(); } }}
//这样我们就保证了链表中数据的统一性,因此可以安全的使用foreach遍历链表了。
//其实,我个人认为,泛型也就是我们在编写代码时并不知道要使用的数据类型是什么,而是在使用代码时规定数据类型的,这样,我们就很容易的创建复用的模板代码,即减少了代码编写的工作,也节省了空间资源。