C语言:链表
链表
- 介绍
- 单向链表
- 节点结构
- 创建节点
- 插入节点
- 删除节点
- 遍历链表
- 尾部插入
- 查找节点
- 链表反转
- 示例程序
- 程序1
- 程序2
介绍
链表是一种常见的数据结构,用于存储一系列线性数据。与数组不同,链表中的元素在内存中不必是连续存放的,而是通过指针将每个元素(节点)链接在一起。链表有很多种类型,例如单向链表、双向链表和循环链表。这里我们主要介绍单向链表。
单向链表
单向链表由一系列节点组成,每个节点包含两个部分:
- 数据部分:存储节点的实际内容。
- 指针部分:存储指向下一个节点的指针。
节点结构
在 C 语言中,我们可以通过定义一个结构体来表示链表的节点:
struct Node {int data; // 数据部分struct Node* next; // 指针部分
};
创建节点
可以通过动态内存分配函数 malloc
来创建新节点:
#include <stdio.h>
#include <stdlib.h>// 定义节点结构
struct Node {int data;struct Node* next;
};// 创建新节点
struct Node* createNode(int data) {struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));if (!newNode) {printf("内存分配失败\n");exit(1);}newNode->data = data;newNode->next = NULL;return newNode;
}
插入节点
我们可以在链表的头部或尾部插入节点。以头部插入为例:
// 头部插入
void insertAtHead(struct Node** head, int data) {struct Node* newNode = createNode(data);newNode->next = *head;*head = newNode;
}
删除节点
删除链表中的节点也很常见。假设我们要删除值为 key
的节点:
void deleteNode(struct Node** head, int key) {struct Node* temp = *head;struct Node* prev = NULL;// 如果头节点本身就是要删除的节点if (temp != NULL && temp->data == key) {*head = temp->next;free(temp); // 释放内存return;}// 搜索要删除的节点while (temp != NULL && temp->data != key) {prev = temp;temp = temp->next;}// 如果没找到要删除的节点if (temp == NULL) return;// 断开链接并释放内存prev->next = temp->next;free(temp);
}
遍历链表
遍历链表可以通过循环来实现:
void printList(struct Node* head) {struct Node* current = head;while (current != NULL) {printf("%d -> ", current->data);current = current->next;}printf("NULL\n");
}
尾部插入
尾部插入与头部插入类似,我们需要找到链表的最后一个节点,然后将新节点添加到末尾。
// 尾部插入
void insertAtTail(struct Node** head, int data) {struct Node* newNode = createNode(data);if (*head == NULL) {*head = newNode;return;}struct Node* temp = *head;while (temp->next != NULL) {temp = temp->next;}temp->next = newNode;
}
查找节点
查找链表中的某个节点,返回其位置或者指针:
struct Node* searchNode(struct Node* head, int key) {struct Node* current = head;while (current != NULL) {if (current->data == key) {return current;}current = current->next;}return NULL; // 未找到
}
链表反转
反转链表是一个经典的问题,可以通过迭代的方式实现:
void reverseList(struct Node** head) {struct Node* prev = NULL;struct Node* current = *head;struct Node* next = NULL;while (current != NULL) {next = current->next; // 暂存下一个节点current->next = prev; // 反转当前节点的指针prev = current; // 移动 prev 指针current = next; // 移动 current 指针}*head = prev;
}
示例程序
程序1
#include <stdio.h>
#include <stdlib.h>struct Node {int data;struct Node* next;
};struct Node* createNode(int data) {struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));if (!newNode) {printf("内存分配失败\n");exit(1);}newNode->data = data;newNode->next = NULL;return newNode;
}void insertAtHead(struct Node** head, int data) {struct Node* newNode = createNode(data);newNode->next = *head;*head = newNode;
}void deleteNode(struct Node** head, int key) {struct Node* temp = *head;struct Node* prev = NULL;if (temp != NULL && temp->data == key) {*head = temp->next;free(temp);return;}while (temp != NULL && temp->data != key) {prev = temp;temp = temp->next;}if (temp == NULL) return;prev->next = temp->next;free(temp);
}void printList(struct Node* head) {struct Node* current = head;while (current != NULL) {printf("%d -> ", current->data);current = current->next;}printf("NULL\n");
}int main() {struct Node* head = NULL;insertAtHead(&head, 1);insertAtHead(&head, 2);insertAtHead(&head, 3);printf("Created Linked List: ");printList(head);deleteNode(&head, 2);printf("Linked List after deletion of 2: ");printList(head);return 0;
}
输出结果:
程序2
#include <stdio.h>
#include <stdlib.h>// 定义节点结构
struct Node {int data;struct Node* next;
};// 创建新节点
struct Node* createNode(int data) {struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));if (!newNode) {printf("内存分配失败\n");exit(1);}newNode->data = data;newNode->next = NULL;return newNode;
}// 头部插入
void insertAtHead(struct Node** head, int data) {struct Node* newNode = createNode(data);newNode->next = *head;*head = newNode;
}// 尾部插入
void insertAtTail(struct Node** head, int data) {struct Node* newNode = createNode(data);if (*head == NULL) {*head = newNode;return;}struct Node* temp = *head;while (temp->next != NULL) {temp = temp->next;}temp->next = newNode;
}// 删除节点
void deleteNode(struct Node** head, int key) {struct Node* temp = *head;struct Node* prev = NULL;if (temp != NULL && temp->data == key) {*head = temp->next;free(temp);return;}while (temp != NULL && temp->data != key) {prev = temp;temp = temp->next;}if (temp == NULL) return;prev->next = temp->next;free(temp);
}// 查找节点
struct Node* searchNode(struct Node* head, int key) {struct Node* current = head;while (current != NULL) {if (current->data == key) {return current;}current = current->next;}return NULL;
}// 反转链表
void reverseList(struct Node** head) {struct Node* prev = NULL;struct Node* current = *head;struct Node* next = NULL;while (current != NULL) {next = current->next;current->next = prev;prev = current;current = next;}*head = prev;
}// 打印链表
void printList(struct Node* head) {struct Node* current = head;while (current != NULL) {printf("%d -> ", current->data);current = current->next;}printf("NULL\n");
}int main() {struct Node* head = NULL;insertAtHead(&head, 1);insertAtHead(&head, 2);insertAtHead(&head, 3);printf("初始链表: ");printList(head);// 测试尾部插入insertAtTail(&head, 4);printf("尾部插入 4 后的链表: ");printList(head);// 测试删除节点deleteNode(&head, 2);printf("删除节点 2 后的链表: ");printList(head);// 测试查找节点struct Node* foundNode = searchNode(head, 3);if (foundNode) {printf("找到节点 3\n");} else {printf("未找到节点 3\n");}// 测试反转链表reverseList(&head);printf("反转后的链表: ");printList(head);return 0;
}
输出结果:
相关文章:

C语言:链表
链表 介绍单向链表节点结构创建节点插入节点删除节点遍历链表尾部插入查找节点链表反转示例程序程序1程序2 介绍 链表是一种常见的数据结构,用于存储一系列线性数据。与数组不同,链表中的元素在内存中不必是连续存放的,而是通过指针将每个元…...

【git使用二】gitee远程仓库创建与本地git命令用法
目录 gitee介绍 管理者注册gitee账号 管理者在gitee网站上创建远程仓库 每个开发者安装git与基本配置 1.git的下载和安装 2.配置SSH公钥 3.开发者信息配置 git命令用法 gitee介绍 Gitee(又称码云)是一个基于Git的代码托管服务,由开源…...

明星百科大全PHP网站源码
源码介绍 明星百科大全网站源码,国内外明星娱乐音乐、新闻八卦、写真照片、相关影视作品等等的明星百科网站源码。 源码截图 源码下载 明星百科大全PHP网站源码...

白酒:茅台镇白酒的品鉴会与文化交流活动
茅台镇,这个位于中国贵州省的小镇,因其与众不同的自然环境和杰出的酿酒工艺而成为世界著名的白酒产区。云仓酒庄豪迈白酒作为茅台镇的品牌,积极参与各种品鉴会和文化交流活动,向世界展示了中国白酒的魅力和文化底蕴。 近年来&…...

python中列表结构在点云数据处理中用法
1、前言 Python中的列表(list)是一种可变的序列类型,用于存储集合数据。列表用途非常广泛,包括但不限于以下几个方面: 存储集合数据:列表用于存储一系列有序的元素,这些元素可以是任何数据类型&…...

土耳其(小亚细亚)历史上的各个阶段
一个国家的历史书写方式有两种,其一是按本国主体民族的渊源,其二是本国国土内发生的都属于本国史。一般来说,这两种方式相当程度上是重合的,但也有例外,比如本文要讲述的土耳其。 土耳其的国土并不辽阔,其…...

Windows下基于Frida查看内存基址和修改寄存器
使用Frida能够方便地获取到DLL基址,还能修改寄存器值。首先要通过任务管理器获得进程的PID,然后写Python脚本把Frida附加到这个PID进程,根据IDA分析出来的函数地址,HOOK到目标函数,修改寄存器的值,最终实现…...

2024中国网络安全产品用户调查报告(发布版)
自2020年始,人类进入了21世纪的第二个十年,全球进入了百年未有之大变局,新十年的开始即被新冠疫情逆转了全球化发展的历程,而至2022年3月俄乌战争又突然爆发,紧接着2023年7月“巴以冲突"皱起,世界快速…...
手写图片懒加载
参考来自前辈 Aidan路修远i 的文章面试官:请你手写一下!懒加载 - 掘金 (juejin.cn) Hello.vue <template><div><!-- src里面为空,data-original里面写图片真正的url(此处省略) --><img src"" data-origina…...

大型语言模型(LLMs)的后门攻击和防御技术
大型语言模型(LLMs)通过训练在大量文本语料库上,展示了在多种自然语言处理(NLP)应用中取得最先进性能的能力。与基础语言模型相比,LLMs在少样本学习和零样本学习场景中取得了显著的性能提升,这得…...
力扣2594.修车的最少时间
力扣2594.修车的最少时间 二分答案 class Solution {public:long long repairCars(vector<int>& ranks, int cars) {ranges::sort(ranks);auto check [&](long long x) -> bool{long long res 0;for(auto v : ranks){long long k sqrt(x/v);res k;if(r…...

攻防演练之-成功的钓鱼邮件溯源
书接上文,《网络安全攻防演练风云》专栏之攻防演练之-网络安全产品大巡礼二,这里。 演练第一天并没有太大的波澜,白天的时间过得很快。夜色降临,攻防演练中心内的灯光依旧明亮。对于网络安全团队来说,夜晚和白天并没有…...

Gi标签管理
文章目录 前言理解标签创建标签操作标签总结 前言 理解标签 标签,可以理解为对某次commit的一次标识,相当于起起了一个别名。 例如,在项目发布某个版本时候,针对最后一次commit起一个v1.0这样的标签来标识里程碑的意义。 这有什…...
2024福建等保测评公司有哪些?分别叫做什么名字?
2024福建等保测评公司有哪些?分别叫做什么名字? 【回答】:2024年具有资质的福建等保测评公司有6家,其名称以及地址如下: 1、福建省网络与信息安全测评中心,福州市鼓楼区东街8号利达大厦A座8层;…...

王先宏老师厉害了,活页笔记版古琴曲谱拆箱图
王先宏老师走心了,活页笔记版古琴曲谱拆箱图,简直是史上最好的古琴学习利器!送的防滑垫还带铝合金夹层的,养弦膏都是市面上没有的的。 这些古琴谱上的笔记就是老师课堂上用的,直接拿来就可以跟着弹,不用您…...

TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台
TalkingData 是一家专注于提供数据统计和分析解决方案的独立第三方数据智能服务平台。通过搜索结果,我们可以了解到 TalkingData 的一些关键特性和市场情况,并将其与同类型产品进行比较。 TalkingData 产品特性 数据统计与分析:提供专业的数…...

Springboot的小型超市商品展销系统-计算机毕业设计源码01635
摘 要 科技进步的飞速发展引起人们日常生活的巨大变化,电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流,人类发展的历史正进入一个新时代。在现实运用中,应用软件的工作…...

UV胶开裂主要因素有哪些?如何避免?
UV胶开裂主要因素有哪些?如何避免? UV胶开裂的原因可能包括多个方面: 固化不足:UV胶的固化需要足够的紫外线照射。如果照射时间不够,或者紫外线光源的强度不足,胶水可能没有完全固化,从而导致开…...

LogicFlow 学习笔记——3. LogicFlow 基础 节点 Node
节点 Node LogicFlow 内置了一些基础节点,开发者在实际应用场景中,可以基于这些基础节点,定义符合自己业务逻辑的节点。 认识基础节点 LogicFlow是基于svg做的流程图编辑框架,所以我们的节点和连线都是svg基本形状,…...

VMware清理拖拽缓存
磁盘空间越用越小,如何快速解决磁盘空间的问题,甩掉烦恼 安装VM tools之后可以通过拖拽的方式把文件拉入虚拟机之中。但每一次拖拽,其实都是现在cache文件夹里面生成一个同样的文件,并使用cp拷贝的方式将其拷贝到拖拽放置的目录中…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...