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拷贝的方式将其拷贝到拖拽放置的目录中…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
