LinkedList<T>是一个双向链表,其元素会指向它前面和后面的元素。这样,通过移动到下一个元素可以正向遍历链表,通过移动到前一个元素可以反向遍历链表。
  
  链表在存储元素时,不仅要存储元素的值,还必须存储每个元素的下一个元素和上一个元素的信息。这就是LinkedList<T>包含LinkedListNode<T>类型的元素的原因。使用LinkedListNode<T>,可以获得列表中的下一个和上一个元素。LinkedListNode<T>定义了属性List,Next,Previous和Value。List属性返回与节点相关的LinkedList<T>对象。Next和Previous属性用于遍历链表,访问当前节点之后和之前的节点。Value属性返回与节点相关的元素,其类型是T。
  链表的优点是,如果将元素插入到列表的中间位置,使用链表就会很快。在插入一个元素时,秩序啊哟修改上一个元素的Next引用和下一个元素的Previous引用,使它们引用所插入的元素。在  List<T>(http://www.cnblogs.com/afei-24/p/6824791.html)中,插入一个元素,需要移动该元素后面的所以元素。
  链表的缺点是,链表元素只能一个接一个的访问,这需要较长时间来查找位于链表中间或尾部的元素。

  LinkedList<T>类定义的成员可以访问链表中的第一个和最后一个元素(First和Last);
  在指定位置插入元素:AddAfter(),AddFirst()和AddLast();
  删除指定位置的元素:Remove(),RemoveFirst(),RemoveLast();
  搜索:Find(),FindLast()。

  下面用一个例子演示链表。在链表中,文档按照优先级来排序。如果多个文档的优先级相同,这些元素就按照文档的插入时间来排序:
  PriorityDocumentManager类使用一个链表LinkedList<Document> documentList和一个列表List<LinkedListNode<Document>> priorityNodes,链表包含Document对象,Document对象包含文档的标题和优先级。列表List<LinkedListNode<Document>> priorityNodes应最多包含10个元素,每个元素分别是引用每个优先级的最后一个文档对象。
  

  

      public class PriorityDocumentManager
{
private readonly LinkedList<Document> documentList; // priorities 0.9
private readonly List<LinkedListNode<Document>> priorityNodes; public PriorityDocumentManager()
{
documentList = new LinkedList<Document>(); priorityNodes = new List<LinkedListNode<Document>>();
for (int i = ; i < ; i++)
{
priorityNodes.Add(new LinkedListNode<Document>(null));
}
} public void AddDocument(Document d)
{
//Contract.Requires<ArgumentNullException>(d != null, "argument d must not be null");
if (d == null) throw new ArgumentNullException("d"); AddDocumentToPriorityNode(d, d.Priority);
} private void AddDocumentToPriorityNode(Document doc, int priority)
{
if (priority > || priority < )
throw new ArgumentException("Priority must be between 0 and 9"); //检查优先级列表priorityNodes中是否有priority这个优先级
if (priorityNodes[priority].Value == null)
{
//如果没有,递减优先级值,递归AddDocumentToPriorityNode方法,检查是否有低一级的优先级
--priority;
if (priority >= )
{
AddDocumentToPriorityNode(doc, priority);
}
else //如果已经没有更低的优先级时,就直接在链表中添加该节点,并将这个节点添加到优先级列表
{
documentList.AddLast(doc);
priorityNodes[doc.Priority] = documentList.Last;
}
return;
}
else //优先级列表priorityNodes中有priority这个优先级
{
LinkedListNode<Document> prioNode = priorityNodes[priority];
//区分优先级列表priorityNodes存在这个指定的优先级值的节点,还是存在较低的优先级值的节点
if (priority == doc.Priority)
// 如果存在这个指定的优先级值的节点
{
//将这个节点添加到链表
documentList.AddAfter(prioNode, doc); // 将这个节点赋予优先级列表中的这个优先级值的节点,因为优先级节点总是引用指定优先级节点的最后一个文档
priorityNodes[doc.Priority] = prioNode.Next;
}
else //如果存在较低的优先级值的节点
{
//在链表中找到这个较低优先级的第一个节点,把要添加的节点放到它前面
LinkedListNode<Document> firstPrioNode = prioNode;
//通过循环,使用Previous找到这个优先级的第一个节点
while (firstPrioNode.Previous != null &&
firstPrioNode.Previous.Value.Priority == prioNode.Value.Priority)
{
firstPrioNode = prioNode.Previous;
prioNode = firstPrioNode;
} documentList.AddBefore(firstPrioNode, doc); // 设置一个新的优先级节点
priorityNodes[doc.Priority] = firstPrioNode.Previous;
}
}
} public void DisplayAllNodes()
{
foreach (Document doc in documentList)
{
Console.WriteLine("priority: {0}, title {1}", doc.Priority, doc.Title);
}
} // returns the document with the highest priority
// (that's first in the linked list)
public Document GetDocument()
{
Document doc = documentList.First.Value;
documentList.RemoveFirst();
return doc;
} } //存储在链表中的元素是Document类型
public class Document
{
public string Title { get; private set; }
public string Content { get; private set; }
public byte Priority { get; private set; } public Document(string title, string content, byte priority)
{
this.Title = title;
this.Content = content;
this.Priority = priority;
}
}

客户端代码:
  

static void Main()
{
PriorityDocumentManager pdm = new PriorityDocumentManager();
pdm.AddDocument(new Document("one", "Sample", ));
pdm.AddDocument(new Document("two", "Sample", ));
pdm.AddDocument(new Document("three", "Sample", ));
pdm.AddDocument(new Document("four", "Sample", ));
pdm.AddDocument(new Document("five", "Sample", ));
pdm.AddDocument(new Document("six", "Sample", ));
pdm.AddDocument(new Document("seven", "Sample", ));
pdm.AddDocument(new Document("eight", "Sample", )); pdm.DisplayAllNodes(); Console.ReadKey(); }

C#集合之链表的更多相关文章

  1. 对象数组、集合、链表(java基础知识十五)

    1.对象数组的概述和使用 * 需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息. Student[] arr = new Student[5]; //存储学生 ...

  2. C#泛型集合之——链表

    链表基础 1.概述:C#中泛型集合中的链表—LinkedList 是一个双向链表,其结点为LinkedListNode 结构 其中,结点结构包含:Next,Previous,Value三部分.且结点中 ...

  3. Java 集合系列01之 总体框架

      Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等.Java集合工具包位置是java.util.*Java集合主要可以划分为4个部分:List列表.Set ...

  4. Java集合系列:-----------01集合的整体框架

    内容来自:http://www.cnblogs.com/skywang12345/p/3308498.html Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映 ...

  5. Java 集合系列 01 总体框架

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  6. java核心技术记录之集合

    java库中的具体集合: 集合类型 描述 ArrayList 一种可以动态增长和缩减的索引序列 LinkedList 一种可以在任何位置进行高效地插入和删除操作的有序序列 ArrarDeque 一种用 ...

  7. 不相交集合ADT

    不相交集合数据结构保持一组不相交的动态集合S={S1,S2,...,SK},每个集合通过一个代表来识别,代表即集合中的某个成员. 如果x表示一个对象,不相交集合支持以下操作: MAKE-SET(x): ...

  8. java集合系列——java集合概述(一)

    在JDK中集合是很重要的,学习java那么一定要好好的去了解一下集合的源码以及一些集合实现的思想! 一:集合的UML类图(网上下载的图片) Java集合工具包位置是java.util.* 二:集合工具 ...

  9. Java集合之Collection

    Java集合是java提供的工具包,包含了常用的数据结构:集合.链表.队列.栈.数组.映射等.Java集合工具包位置是java.util.* Java集合主要可以划分为4个部分:List列表.Set集 ...

随机推荐

  1. WebService从服务端到客户端的用例

    1.首先编写Wsdl(基于契约优先的方式),要注意的是命名空间(若是使用include或import)最好使用一致的,代码如下: <?xml version="1.0" en ...

  2. Linux之kill,pkill,killall命令

    kill,pkill,killall这些命令都是用来杀死进程的 查找进程的方法: ps -ef|grep pidof 进程名 ps命令 http://www.cnblogs.com/along1226 ...

  3. unity传送门类似效果实现

    简述 在传送门中,核心的玩法是在地上或者墙上打开2个可以联通的洞来实现传送的效果.以此扩展加入解谜要素构成游戏的核心. 这里尝试使用unity来实现传送门的核心功能,具体功能分析如下: 1.传送门的模 ...

  4. 学习Jammendo代码的心路历程(二)ViewFlipper数据的填充

    打开Jammendo进入到首页之后,会看到这样一个界面.可以看到下左效果,我们可以看到,他是上部分的ViewFlipper模块和下半部分的listview模块构成的,今天就简单的说一下Jammendo ...

  5. 通过哨兵机制实现Redis主从配置以及java调用

    Redis版本:3.0.7 操作环境:Linux 一.redis 主从配置的作用是什么 redis主从配置,配置master 只能为写,slave只能为读,在客户端对poolconnect请求时候,, ...

  6. 【转】使用VS开发 Node.js指南

    参考:https://www.visualstudio.com/features/node-js-vs 这篇文章主要介绍了使用VS开发 Node.js的方法,主要是使用NTVS(Node.js Too ...

  7. Laravel查询构造器的使用方法整理

    1.结果集 1.1从一张表获取所有行,get方法获取所有行 $users = DB::table('users')->get(); 获取列的值 foreach ($users as $user) ...

  8. 手机自动化测试:appium问题解决

    手机自动化测试:appium问题解决   Appium遇到问题: 问题一:问题org.openqa.selenium.remote.UnreachableBrowserException: Could ...

  9. Java中一个方法只被一个线程调用一次

    1.想在运行时抛出异常,终止方法的运行 private final Set<Long> THREADS = new HashSet<>(); public void someM ...

  10. mock.js-无需等待,随机产生数据,让前端独立于后端进行开发

    mock.js所做的 基于 数据模板 生成模拟数据. 基于 HTML模板 生成模拟数据. 拦截并模拟 ajax 请求. Mock.js官方网址:http://mockjs.com/ 1.Mock.js ...