C# 中的 LinkedList

一、概述

LinkedList<T> 是 .NET 标准库(System.Collections.Generic 命名空间)中提供的一种泛型双向链表实现。

其本质特征如下:

  • 采用 双向链表(Doubly Linked List) 结构
  • 每个节点通过引用连接前驱节点和后继节点
  • 不支持基于索引的随机访问
  • 提供高效的节点级插入与删除操作

二、类定义与继承体系

csharp 复制代码
public class LinkedList<T> : 
    ICollection<T>, 
    ICollection, 
    IReadOnlyCollection<T>, 
    IEnumerable<T>, 
    IEnumerable, 
    ISerializable, 
    IDeserializationCallback

关键说明:

  • 不实现 IList<T>

    • 表明其不支持索引访问(如 list[0]
  • 提供集合基础能力(枚举、计数、复制等)

  • 支持序列化与反序列化


三、内部数据结构

1. 节点结构:LinkedListNode<T>

csharp 复制代码
public sealed class LinkedListNode<T>
{
    public T Value { get; set; }
    public LinkedListNode<T>? Next { get; }
    public LinkedListNode<T>? Previous { get; }
    public LinkedList<T>? List { get; }
}

特点:

  • 每个节点同时保存:

    • 当前值 Value
    • 前驱节点 Previous
    • 后继节点 Next
  • 节点与链表实例绑定,不能在多个链表之间共享


2. 链表整体结构

  • 维护:

    • 头节点 First
    • 尾节点 Last
    • 元素数量 Count
  • 内部逻辑结构为 首尾相连的双向循环链表(实现细节)


四、核心属性

属性 说明
First 获取第一个节点
Last 获取最后一个节点
Count 元素数量
csharp 复制代码
LinkedList<int> list = new LinkedList<int>();
LinkedListNode<int>? first = list.First;

五、核心方法分类

1. 添加元素

基于值的添加

csharp 复制代码
AddFirst(T value)
AddLast(T value)

基于节点的添加

csharp 复制代码
AddBefore(LinkedListNode<T> node, T value)
AddAfter(LinkedListNode<T> node, T value)

示例

csharp 复制代码
var list = new LinkedList<int>();
var node = list.AddLast(10);
list.AddAfter(node, 20);

2. 删除元素

csharp 复制代码
Remove(T value)
Remove(LinkedListNode<T> node)
RemoveFirst()
RemoveLast()
Clear()

注意事项:

  • Remove(T value) 删除的是第一个匹配项
  • 删除节点操作为 O(1)(前提是已持有节点引用)

3. 查找元素

csharp 复制代码
Find(T value)
FindLast(T value)
  • 返回 LinkedListNode<T>?
  • 查找时间复杂度为 O(n)

4. 枚举遍历

csharp 复制代码
foreach (var item in list)
{
    // 顺序遍历
}
  • 遍历顺序:从 FirstLast
  • 枚举期间修改集合会抛出 InvalidOperationException

六、时间与空间复杂度分析

操作 时间复杂度
头/尾插入 O(1)
已知节点插入 O(1)
已知节点删除 O(1)
查找 O(n)
遍历 O(n)

空间开销

  • 每个节点额外维护两个引用(PreviousNext
  • 相比数组型集合,内存占用更高

七、使用规范与注意事项

1. 何时应使用 LinkedList<T>

适用场景:

  • 频繁插入和删除
  • 操作对象是"节点位置",而非索引
  • 需要在遍历过程中进行结构修改

2. 不适合的场景

不推荐用于:

  • 高频随机访问
  • 仅进行尾部追加(List<T> 性能更优)
  • 数据量较小且结构简单的集合

3. 节点使用规范

❌ 错误示例(跨链表使用节点):

csharp 复制代码
var list1 = new LinkedList<int>();
var list2 = new LinkedList<int>();
var node = list1.AddLast(1);
list2.AddLast(node); // 抛异常

✅ 正确做法:

  • 每个 LinkedListNode<T> 只能属于一个链表

八、与 List<T> 的关键差异

维度 LinkedList List
底层结构 双向链表 动态数组
随机访问 不支持 支持
插入删除 高效 中间位置代价高
内存占用 较高 较低
常用性 较低 非常高

九、设计层面的总结

  • LinkedList<T>面向节点操作的集合

  • 其价值在于:

    • 常量时间的结构性修改
    • 明确的前驱 / 后继关系
  • 在现代 .NET 应用中属于特定场景下的工具型集合,而非通用首选

相关推荐
我是唐青枫1 天前
C#.NET gRPC 深入解析:Proto 定义、流式调用与服务间通信取舍
开发语言·c#·.net
JJay.1 天前
Kotlin 高阶函数学习指南
android·开发语言·kotlin
bazhange1 天前
python如何像matlab一样使用向量化替代for循环
开发语言·python·matlab
jinanwuhuaguo1 天前
截止到4月8日,OpenClaw 2026年4月更新深度解读剖析:从“能力回归”到“信任内建”的范式跃迁
android·开发语言·人工智能·深度学习·kotlin
froginwe111 天前
CSS 创建:从基础到高级
开发语言
unicrom_深圳市由你创科技1 天前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
无限进步_1 天前
【C++】电话号码的字母组合:从有限处理到通用解法
开发语言·c++·ide·windows·git·github·visual studio
JJay.1 天前
Android Kotlin 协程使用指南
android·开发语言·kotlin
csbysj20201 天前
jQuery 捕获详解
开发语言
C++ 老炮儿的技术栈1 天前
GCC编译时无法向/tmp 目录写入临时汇编文件,因为设备空间不足,解决
linux·运维·开发语言·汇编·c++·git·qt