导读:本期聚焦于小伙伴创作的《什么是.NET框架中的双向链表LinkedList,它的底层实现逻辑是怎样的》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《什么是.NET框架中的双向链表LinkedList,它的底层实现逻辑是怎样的》有用,将其分享出去将是对创作者最好的鼓励。

双向链表是链式存储结构的一种,每个节点除了存储自身数据,还会保存指向前一个节点和后一个节点的引用,这种设计让链表在任意位置的插入和删除操作都可以避免大量元素的移动。.NET框架中的LinkedList就是基于这种双向链表结构实现的泛型集合,适合需要频繁修改集合内容的场景。

什么是.NET框架中的双向链表LinkedList,它的底层实现逻辑是怎样的

LinkedList的核心节点结构

LinkedList的底层核心是LinkedListNode<T>节点类,每个节点包含数据、前驱节点引用和后继节点引用三个核心部分,同时还会关联到所属的LinkedList实例,避免节点被随意插入到不匹配的链表中。下面是简化后的节点结构示意:

internal sealed class LinkedListNode<T>
{
    // 节点存储的实际数据
    internal T item;
    // 指向前一个节点的引用
    internal LinkedListNode<T> prev;
    // 指向后一个节点的引用
    internal LinkedListNode<T> next;
    // 该节点所属的LinkedList实例
    internal LinkedList<T> list;

    // 构造函数,初始化节点数据和所属链表
    internal LinkedListNode(T value, LinkedList<T> linkedList)
    {
        item = value;
        list = linkedList;
    }

    // 对外暴露的属性,获取节点数据
    public T Value
    {
        get { return item; }
        set { item = value; }
    }

    // 获取前驱节点
    public LinkedListNode<T> Previous
    {
        get { return prev; }
    }

    // 获取后继节点
    public LinkedListNode<T> Next
    {
        get { return next; }
    }

    // 获取所属链表
    public LinkedList<T> List
    {
        get { return list; }
    }
}

LinkedList的核心属性与字段

LinkedList类本身会维护链表的头节点、尾节点和节点数量,通过这些字段可以快速获取链表的基本信息,同时保证操作的正确性。核心字段和属性如下:

  • head:链表头节点引用,第一个节点的prev为null
  • tail:链表尾节点引用,最后一个节点的next为null
  • count:链表中节点的总数量
  • Count属性:对外暴露的节点数量,直接返回count字段的值
  • First属性:返回头节点head
  • Last属性:返回尾节点tail

核心操作实现逻辑

添加节点操作

LinkedList提供了在头部、尾部以及指定节点前后添加节点的方法,所有添加操作都会创建新的LinkedListNode实例,然后调整相关节点的前后引用关系,不需要移动其他节点。以在链表尾部添加节点为例,实现逻辑如下:

public LinkedListNode<T> AddLast(T value)
{
    // 创建新的节点,关联到当前链表
    LinkedListNode<T> newNode = new LinkedListNode<T>value, this);
    if (head == null)
    {
        // 如果链表为空,新节点同时作为头节点和尾节点
        head = newNode;
        tail = newNode;
    }
    else
    {
        // 否则将新节点链接到尾节点之后,更新尾节点引用
        tail.next = newNode;
        newNode.prev = tail;
        tail = newNode;
    }
    count++;
    return newNode;
}

删除节点操作

删除节点时,只需要调整被删除节点前后节点的引用关系,跳过被删除的节点即可,时间复杂度为O(1),前提是需要拿到要删除的节点引用。如果是按值删除,需要先遍历找到对应节点,时间复杂度为O(n)。下面是在任意位置删除节点的核心逻辑:

public void Remove(LinkedListNode<T> node)
{
    // 校验节点是否属于当前链表
    if (node == null || node.list != this)
    {
        throw new InvalidOperationException("节点不属于当前链表");
    }
    LinkedListNode<T> prevNode = node.prev;
    LinkedListNode<T> nextNode = node.next;
    if (prevNode != null)
    {
        // 调整前驱节点的后继引用
        prevNode.next = nextNode;
    }
    else
    {
        // 如果被删除的是头节点,更新头节点引用
        head = nextNode;
    }
    if (nextNode != null)
    {
        // 调整后继节点的前驱引用
        nextNode.prev = prevNode;
    }
    else
    {
        // 如果被删除的是尾节点,更新尾节点引用
        tail = prevNode;
    }
    // 清空被删除节点的关联信息
    node.prev = null;
    node.next = null;
    node.list = null;
    count--;
}

查找节点操作

LinkedList没有像List那样支持索引访问,查找节点需要从头节点或者尾节点开始逐个遍历,直到找到匹配的节点或者遍历完整个链表。按值查找的实现逻辑如下:

public LinkedListNode<T> Find(T value)
{
    // 从前往后遍历节点
    LinkedListNode<T> current = head;
    // 处理值可能为null的情况
    if (value == null)
    {
        while (current != null)
        {
            if (current.item == null)
            {
                return current;
            }
            current = current.next;
        }
    }
    else
    {
        // 使用默认比较器比较值
        EqualityComparer<T> comparer = EqualityComparer<T>.Default;
        while (current != null)
        {
            if (comparer.Equals(current.item, value))
            {
                return current;
            }
            current = current.next;
        }
    }
    return null;
}

LinkedList与List的对比

两种集合的设计思路不同,适用场景也有明显区别,具体对比如下:

对比维度LinkedListList<T>
内存结构非连续内存,节点分散存储连续内存,基于数组实现
插入删除效率已知节点位置时O(1),按值查找后删除为O(n)非尾部位置操作需要移动元素,平均O(n)
查找效率只能遍历查找,O(n)支持索引访问O(1),二分查找O(log n)
内存开销每个节点额外存储前后引用,开销更大仅存储数据和数组额外容量,开销更小
适用场景频繁插入删除、不需要随机访问的场景频繁查询、尾部添加为主的场景

使用注意事项

  • LinkedList的节点不能跨链表使用,每个节点都绑定了所属的链表实例,强行插入其他链表的节点会抛出异常
  • 遍历LinkedList时如果使用foreach,不要直接在遍历过程中修改链表结构,否则会触发迭代器异常,需要修改的话可以先记录要操作的节点,遍历完成后再处理
  • 如果需要频繁按值查找然后操作节点,LinkedList的效率不如Dictionary或者HashSet配合List使用,要根据实际场景选择

LinkedList双向链表数据结构.NET集合修改时间:2026-06-02 21:20:19

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。