LinkedList<T>是一个双向链表,其元素指向它前面和后面的元素。
优点:如果将元素插入到列表的中间位置,使用链表就会非常快。在插入一个元素时,只需要修改上一个元素的Next引用和下一个元素的Previous引用,使它们引用所插入的元素。在List<T>类中,插入一个元素时,需要移动该元素后面的所有元素。
缺点:链表的元素只能一个接一个地访问,这需要较长的时间来查找位于链表中间或尾部的元素。
另外需要注意的一点:链表不能再列表中仅存储元素。存储元素时,链表还必须存储每个元素的下一个元素和上一个元素的信息。这也是为什么LinkedList<T>包含LinkedListNode<T>类型的元素的原因。
其中LinkedListNode<T>定义了属性List、Next、Previous和Value。List属性返回与节点相关的LinkedList<T>对象,Next和Previouss属性用于遍历链表,访问当前节点之后和之前的节点。value返回与节点相关的元素,其类型是T。
LinkedList<T>类定义的成员可以访问链表中的第一个和最后一个元素(First和Last)、在指定位置插入元素方法有AddAfter()、AddBefore()、AddFirst()和AddLast()方法,删除指定位置的元素有Remove()、RemoveFirst()和RemoveLast()方法,从链表的开头(Find()方法)或结尾(FindLast()方法)开始搜索元素。
书上有一个案例:大体流程是这样:添加一批文档,根据优先级和创建时间进行排序展示;
直接看书中的代码:
/// <summary>
/// 创建一个文档类
/// </summary>
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;
}
}
/// <summary>
/// 对文档进行链表存储处理
/// </summary>
public class PriorityDocumentManager
{
private readonly LinkedList<Document> _documentList;
private readonly List<LinkedListNode<Document>> _priorityNodes;
public PriorityDocumentManager()
{
//构造实例
_documentList = new LinkedList<Document>();
_priorityNodes = new List<LinkedListNode<Document>>(10);
for (int i = 0; i < 10; i++)
{
_priorityNodes.Add(new LinkedListNode<Document>(null));
}
}
public void AddDocument(Document d)
{
if (d == null) throw new ArgumentNullException("d");
AddDocumentToPriorityNode(d, d.Priority);
}
private void AddDocumentToPriorityNode(Document doc, int priority)
{
if (priority > 9 || priority < 0)
{
throw new ArgumentNullException("Priority must be between 0 and 9");
}
if (_priorityNodes[priority].Value == null)//不存在优先级节点
{
--priority;
if (priority >= 0)//递归函数
{
//检查下一个较低优先级
AddDocumentToPriorityNode(doc, priority);
}
else //现在不存在具有相同优先级或更低优先级的优先级节点,请将新文档添加到结尾
{
_documentList.AddLast(doc);
_priorityNodes[doc.Priority] = _documentList.Last;
}
return;
}
else //存在优先级节点
{
LinkedListNode<Document> prioNode = _priorityNodes[priority];
if (priority == doc.Priority)//存在具有相同优先级的优先级节点
{
//相同优先级节点根据存储时间追加到节点之后
_documentList.AddAfter(prioNode, doc);
//设置优先级较低的节点
_priorityNodes[doc.Priority] = prioNode.Next;
}
else//仅存在具有较低优先级的优先级节点
{
//获取优先级较低的第一个节点
LinkedListNode<Document> firstPrioNode = prioNode;
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:{doc.Priority},title:{doc.Title}");
}
}
}
//调用方式
var pdm = new PriorityDocumentManager();
pdm.AddDocument(new Document("one", "Sample", 8));
pdm.AddDocument(new Document("two", "Sample", 3));
pdm.AddDocument(new Document("three", "Sample", 4));
pdm.AddDocument(new Document("four", "Sample", 8));
pdm.AddDocument(new Document("five", "Sample", 1));
pdm.AddDocument(new Document("six", "Sample", 9));
pdm.AddDocument(new Document("seven", "Sample", 1));
pdm.AddDocument(new Document("eight", "Sample", 1));
pdm.DisplayAllNodes();
Console.ReadLine();
看完书上的实现方式:
现在我们自己构造一个场景去实现它;
情景如下:书店老板进来一批书籍,有高尔基的《童年》、《在人间》、《我的大学》;老舍的《骆驼祥子》、《四世同堂》、《茶馆》;其他名人的相关书籍《C#编程艺术》、《WepApi的设计理念》、《MVC对WebForm的改进之处》;现在它们顺序是乱的;顺序如下:1.《童年》、2.《骆驼祥子》、3.《C#编程艺术》、4.《WepApi的设计理念》、5.MVC对WebForm的改进之处》、1.《在人间》、2.《四世同堂》、1.《我的大学》、2.《茶馆》;现在我们通过链表的方式对他们进行存储并归类,实现方式如下:
/// <summary>
/// 书
/// </summary>
public class Book
{
public int ID { get; set; }
public string BookName { get; set; }
public Book(int id, string bookName)
{
this.ID = id;
this.BookName = bookName;
}
}
public class BookManager<T> where T : Book
{
/// <summary>
/// 链表集合
/// </summary>
private LinkedList<T> bookList;
/// <summary>
/// 队列集合
/// </summary>
private List<LinkedListNode<T>> books;
public BookManager()
{
bookList = new LinkedList<T>();
books = new List<LinkedListNode<T>>();
for (int i = 0; i < 9; i++)
{
books.Add(new LinkedListNode<T>(null));
}
}
public void AddBook(T model)
{
if (model == null) throw new ArgumentNullException("model");
AddBookToNode(model, model.ID);
}
private void AddBookToNode(T model, int id)
{
if (books[id].Value == null)//该节点没有值
{
//递减查看是否有重复
--id;
if (id >= 0)
AddBookToNode(model, id);
else//不存在相同的优先级,或更低的优先级的节点
{
bookList.AddLast(model);
books[model.ID] = bookList.Last;
}
return;
}
else //存在优先级节点
{
LinkedListNode<T> prioNode = books[id];
if (id == model.ID)//存在具有相同优先级的优先级节点
{
//相同优先级节点根据存储时间追加到节点之后
bookList.AddAfter(prioNode, model);
//设置优先级较低的节点
books[model.ID] = prioNode.Next;
}
else//仅存在具有较低优先级的优先级节点
{
//获取优先级较低的第一个节点
LinkedListNode<T> firstPrioNode = prioNode;
while (firstPrioNode.Previous != null && firstPrioNode.Previous.Value.ID == prioNode.Value.ID)
{
firstPrioNode = prioNode.Previous;
prioNode = firstPrioNode;
}
bookList.AddBefore(firstPrioNode, model);
//将优先级节点设置为新值
books[model.ID] = firstPrioNode.Previous;
}
}
}
public void DisplayAllNodes()
{
foreach (Book doc in bookList)
{
Console.WriteLine($"ID:{doc.ID},BookName:{doc.BookName}");
}
}
}
//调用方式
var pdm = new BookManager<Book>();
pdm.AddBook(new Book(1, "《童年》"));
pdm.AddBook(new Book(2, "《骆驼祥子》"));
pdm.AddBook(new Book(3, "《C#编程艺术》"));
pdm.AddBook(new Book(4, "《WepApi的设计理念》"));
pdm.AddBook(new Book(5, "《MVC对WebForm的改进之处》"));
pdm.AddBook(new Book(1, "《在人间》"));
pdm.AddBook(new Book(2, "《四世同堂》"));
pdm.AddBook(new Book(1, "《我的大学》"));
pdm.AddBook(new Book(2, "《茶馆》"));
pdm.DisplayAllNodes();
Console.ReadLine();