今天来介绍一下LinkedList
LinkedList是一个双向链表结构的容器,其内部为非连续的内存空间。LinkedList包含的主要成员示例如下:
//起始LinkedListNode节点
internal LinkedListNode? head;
//LinkedList中包含的数据数量
internal int count;
//版本号,用于检测LinkedList是否被修改
internal int version;
public sealed class LinkedListNode
{
// 存储的数据对象
internal T item;
//下一个LinkedListNode节点
internal LinkedListNode? next;
//上一个LinkedListNode节点
internal LinkedListNode? prev;
}
LinkedListNode是LinkedList中一个重要的数据结构,其中包含了三个成员变量:
LinkedListNode
int count记录的是LinkedList中存储数据的数量。
int version记录的是版本号信息,用于检测LinkedList是否被修改,每次LinkedList修改时version会加1处理。
LinkedList有多种添加数据的方式,方法如下:
添加数据的过程为先创建一个新的LinkedListNode对象,然后根据不同的方法,将LinkedListNode对象插入到指定节点的前面或者后面。这里以AddLast举例,示例代码如下:
public LinkedListNode AddLast(T value)
{
LinkedListNode result = new LinkedListNode(this, value);
if (head == null)
{
InternalInsertNodeToEmptyList(result);
}
else
{
InternalInsertNodeBefore(head, result);
}
return result;
}
private void InternalInsertNodeBefore(LinkedListNode node, LinkedListNode newNode)
{
newNode.next = node;
newNode.prev = node.prev;
node.prev!.next = newNode;
node.prev = newNode;
version++;
count++;
}
这里讲解一下InternalInsertNodeBefore方法,由于LinkedList是双向链表,在调用AddLast方法在尾部添加数据时,newNode.next的下一个节点也就是head节点,head的上一个节点会被设置为newNode.prev对象。略微有点绕,不过简单推导一下基本可以理解。
LinkedList同样有多种移除数据的方法,示例如下:
几个方法移除数据的过程基本相同,这里以Remove(T value)示例,示例代码如下:
public bool Remove(T value)
{
LinkedListNode? node = Find(value);
if (node != null)
{
InternalRemoveNode(node);
return true;
}
return false;
}
internal void InternalRemoveNode(LinkedListNode node)
{
if (node.next == node)
{
head = null;
}
else
{
node.next!.prev = node.prev;
node.prev!.next = node.next;
if (head == node)
{
head = node.next;
}
}
node.Invalidate();
count--;
version++;
}
移除数据的主要过程在InternalRemoveNode(LinkedListNode
先来介绍一下用foreach遍历LinkedList,foreach是从头到尾逐个遍历LinkedList。需要注意的是遍历过程中不能对LinkedList进行插入/删除操作,不然会抛出异常。示例代码如下:
LinkedList list = new LinkedList();
// 添加元素...
foreach (string item in list)
{
Console.WriteLine(item);
}
其次是用for循环遍历LinkedList,for循环的好处在于可以正向遍历,也可以反向遍历,并且在遍历过程中可以对LinkedList进行插入/删除操作。示例代码如下:
// 正向遍历
for (LinkedListNode node = list.First; node != null; node = node.Next)
{
Console.WriteLine(node.Value);
}
// 反向遍历
for (LinkedListNode node = list.Last; node != null; node = node.Previous)
{
Console.WriteLine(node.Value);
}
LinkedList
LinkedList源码地址:https://github.com/dotnet/runtime/blob/main/src/libraries/System.Collections/src/System/Collections/Generic/LinkedList.cs