当前位置: 首页 > news >正文

单链表C语言实现

1. 单链表的核心概念

  • 单链表(Singly Linked List) 是一种线性数据结构,通过节点间的指针链接实现元素存储。
  • 节点结构
typedef struct SListNode {SLTDataType data;     // 数据域struct SListNode* next; // 指针域
} SLTNode;
  • 核心特性

  1. 内存非连续,通过指针动态连接。
  2. 插入/删除操作高效(时间复杂度 O(1)~O(n))。
  3. 不支持随机访问,查找需遍历。

2. 单链表的C语言实现

 (1)节点创建与初始化

SLTNode* SLTBuyNode(SLTDataType x) {SLTNode* newnode = malloc(sizeof(SLTNode));newnode->data = x;newnode->next = NULL;return newnode;
}
  • 作用:动态分配节点内存,初始化数据域和指针域。

(2) 插入操作

  • 头部插入:直接修改头指针,时间复杂度 O(1)。
void SLTPushFront(SLTNode** pphead, SLTDataType x) {SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}
  • 尾部插入:遍历找到尾节点后插入,时间复杂度 O(n)。
void SLTPushBack(SLTNode** pphead, SLTDataType x) {assert(pphead);SLTNode* newnode = SLTBuyNode(x);if (*pphead == NULL) { *pphead = newnode;}else {SLTNode* ptail = *pphead;while (ptail->next != NULL) { ptail = ptail->next;}ptail->next = newnode; }
}
  • 指定位置插入:需找到前驱节点,时间复杂度 O(n)。

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);if (pos == *pphead){SLTPushFront(pphead, x);//如果pos是头节点,执行头插return;}SLTNode* newnode = SLTBuyNode(x);SLTNode* prev = *pphead;while (prev->next != pos)//寻找pos的前一个节点{prev = prev->next;}newnode->next = pos;//newnode的next指向pos,此时newnode->next和prev->next同时指向posprev->next = newnode;//prev->next指向由原来的pos断开(现在只有一个newnode->next指向原来开的pos),转向newnode,newnode此时就占据了原来pos的位置,完成插入}

(3) 删除操作

  •  头部删除:直接移动头指针,时间复杂度 O(1)。

void SLTPopFront(SLTNode** pphead) {SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
  • 尾部删除:遍历找到倒数第二个节点,时间复杂度 O(n)。

void SLTPopBack(SLTNode** pphead) {assert(pphead && *pphead); // 链表不能为空if ((*pphead)->next == NULL) { // 只有一个节点free(*pphead);*pphead = NULL;}else {SLTNode* prev = NULL;SLTNode* ptail = *pphead;while (ptail->next != NULL) { // 找到尾节点和前驱节点prev = ptail;ptail = ptail->next;}prev->next = NULL; // 断开尾节点free(ptail);}
}

(4) 链表销毁

void SListDesTroy(SLTNode** pphead) {SLTNode* pcur = *pphead;while (pcur) {SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
  • 关键点:逐个释放节点,避免内存泄漏。

3. 时间复杂度分析 

操作时间复杂度说明
头部插入/删除O(1)直接操作头指针
尾部插入/删除O(n)需遍历找到尾节点
指定位置插入/删除O(n)需遍历找到前驱节点
查找O(n)最坏情况遍历整个链表

4 注意事项

  • 指针操作

  1. 使用双重指针 SLTNode** 修改头指针地址:为了在函数内部能够直接修改外部头指针的地址,确保链表操作(如插入、删除头节点)能正确更新头指针。这是C语言中实现“通过函数修改指针”的标准方法。
  2. 插入/删除时需注意前驱节点的链接关系。
场景是否需要双重指针原因
修改头指针的值需要直接操作外部头指针的地址
仅修改链表节点内容单指针已能通过地址修改节点数据
插入/删除头节点头指针本身需要被更新
插入/删除中间或尾部节点只需操作节点间的指针,不涉及头指针
  • 边界处理

  1. 空链表时的插入/删除处理。
  2. 头节点和尾节点的特殊操作。

 

http://www.xdnf.cn/news/578683.html

相关文章:

  • Web项目流程总结
  • 第七章:数据存储策略与状态恢复机制实录
  • Bently Nevada 3500/61 非隔离I/O模块 (133819-02)
  • 一命通关单调栈
  • 工业轴承故障检测技术现状:中国智造的突破与挑战
  • 微信小程序自行diy选择器有效果图
  • 第20天-python生成word文档
  • 《MQTT 从 0 到 1:原理、实战与面试指南全解》
  • PostgreSQL相比Oracle有哪些优势?
  • 一朵由钢片织成的云 ——超“限”的结构
  • 精通Python:使用Pandas进行数据处理与分析
  • PortgreSQL常用操作
  • AI应用电商篇汇总(持续补充)
  • 让蜂鸣器报警并退出
  • 判断一个元素是否在可视区域
  • 嵌入式学习的第二十五天-系统编程-标准I0与文件IO
  • Agentic Loop与MCP:大模型能力扩展技术解析
  • 06 接口自动化-框架封装思想建立之httprunner框架(下)
  • 算法--js--电话号码的字母组合
  • Manus与DeepSeek 的区别
  • 从0开始学linux韦东山教程第四章问题小结(2)
  • Java异步编程利器:CompletableFuture 深度解析与实战
  • 【C++ Primer 学习札记】函数传参问题
  • 轻量级高性能Rust HTTP服务器库Hyperlane,助力现代网络服务开发
  • C++:vector容器
  • 心知天气 API 获取天气预报 2025/5/21
  • QML定时器Timer和线程任务WorkerScript
  • 大模型评测与可解释性
  • Day 27 训练
  • Linux中的文件介绍