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拷贝的方式将其拷贝到拖拽放置的目录中…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
