2025.1.8-1 链表(基础内容)

1)概念:是数据结构,既数据存放(集合)的思想。类似于数组,有着连续的地址,但是数组这样的内存地址难以增减,无法随意加减(不灵活),而链表就解决了这个问题,链表的每一项元素都是结构体。因为结构体内有指针变量(指针变量可以随意更改指针指向结构体),可以随意增减链表内容。

2)具体:链表是一种常见的基础数据结构,它由一系列节点组成,这些节点通过指针(在一些语言中类似指针的机制)相互连接,形成一个链式结构。

2.1)链表的结构

节点:链表的基本组成单元是节点。每个节点至少包含两个部分:数据域和指针域。数据域用于存储实际的数据,指针域则存储指向下一个节点的地址(或引用)。以一个简单的整数链表为例,节点的结构可能如下(以 C 语言结构体表示):

struct ListNode {
    int data;        // 数据域,存储整数
    struct ListNode* next; // 指针域,指向下一个节点
};

头指针:链表通过一个头指针来标识整个链表。头指针指向链表的第一个节点。如果链表为空,头指针通常为NULL。通过头指针,可以方便地访问链表中的所有节点。

2.2)链表的类型

单链表:每个节点只有一个指针,指向下一个节点。单链表的优点是结构简单,易于实现;缺点是只能从链表头开始顺序访问节点,若要访问某个节点,必须从头节点开始遍历。

双链表:每个节点除了有一个指向下一个节点的指针(next),还有一个指向前一个节点的指针(prev)。这使得双链表可以双向遍历,在某些操作(如删除节点)上比单链表更高效,但需要额外的空间来存储前驱指针。双链表节点结构(以 C 语言结构体表示)如下:

struct DoubleListNode {
    int data;
    struct DoubleListNode* prev;
    struct DoubleListNode* next;
};

循环链表:循环链表分为循环单链表和循环双链表。在循环单链表中,最后一个节点的指针不是指向NULL,而是指向头节点,形成一个环形结构。循环双链表类似,只是双向都形成循环。循环链表的优点是可以从任意节点开始遍历整个链表,常用于实现一些需要循环操作的数据结构,如循环队列。

2.3)链表的基本操作

  1. 插入节点
    • 头插法:在链表头部插入新节点。首先创建新节点,然后将新节点的指针指向原头节点,最后更新头指针指向新节点。这使得新节点成为链表的第一个节点。
    • 尾插法:在链表尾部插入新节点。需要遍历链表找到最后一个节点(即指针为NULL的节点),然后将该节点的指针指向新节点。
    • 指定位置插入:在链表的指定位置(例如第k个节点之后)插入新节点。先找到第k个节点,然后让新节点的指针指向第k个节点的下一个节点,再让第k个节点的指针指向新节点。
  2. 删除节点
    • 首先找到要删除节点的前驱节点(在双链表中,也可以通过后继节点找到要删除的节点)。然后调整前驱节点的指针,使其跳过要删除的节点,直接指向要删除节点的下一个节点。如果是双链表,还需要调整后继节点的前驱指针。最后释放被删除节点所占用的内存空间。
  3. 查找节点:从链表头开始,依次比较每个节点的数据域与要查找的数据。如果找到匹配的数据,则返回该节点的指针;如果遍历完整个链表都没有找到,则返回NULL。在单链表中,查找时间复杂度为,其中n是链表的长度,因为最坏情况下需要遍历所有节点。

2.4)链表的应用场景

  1. 操作系统内存管理:操作系统在分配和释放内存时,常使用链表来管理空闲内存块。链表可以方便地插入和删除空闲内存块,以适应不同大小的内存分配请求。
  2. 哈希表冲突解决:在哈希表中,当发生哈希冲突(多个元素映射到同一个哈希桶)时,可以使用链表来存储冲突的元素。每个哈希桶对应一个链表,冲突的元素依次插入到链表中。
  3. 实现栈和队列:可以用链表来实现栈和队列。用链表实现栈时,头插法和删除头节点操作可模拟栈的入栈和出栈;实现队列时,尾插法和删除头节点操作可模拟队列的入队和出队。与数组实现相比,链表实现的栈和队列在动态增长和减少元素时更灵活,不需要预先分配固定大小的空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值