C语言链表详解附实例

article/2025/9/14 12:10:12

C语言链表详解附实例

什么是链表

链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。链表和数组比较,不用事先确定存储空间,而是根据需要开辟内存单元。
下图1是最简单的一种链表(单向链表)的结构
图一
第 0 个结点称为头结点,它存放有第一个结点的首地址,它没有数据,只是一个指针变量。以下的每个结点都分为两个域,一个是数据域,存放各种实际的数据,如学号 num,姓名 name,性别 sex 和成绩 score 等。另一个域为指针域,存放下一结点的首地址。链表中的每一个结点都是同一种结构类型。

环境构建

用的Visual Studio 2019软件
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在源文件中添加C文件
在这里插入图片描述

建立静态链表

包含所需要的头文件

#include<stdio.h> //标准输入输出头文件
#include<stdlib.h>//包含了C、C++语言的最常用的系统函数

宏定义相关变量

#define LEN sizeof(struct Student)//宏定义节点长度得命名
#define TYPE struct Student//宏定义结构体变量命名

创建一个结构体

struct Student//定义一个学生类型结构体,包括学号,分数
{long num;float score;struct Student* next;//next是指针变量,指向结构体变量
};
//指向结构体对象得指针变量既可以指向结构体变量,也可以指向结构体数组中得元素

主函数

int main()
{TYPE* head,*p;//定义头指针struct Student a,b,c;//定义三个结构体变量a.num = 101; a.score = 20;//分别对三个结点赋值b.num = 102; b.score = 20;c.num = 103; c.score = 20;/*1、A.B则A为对象或者结构体2、A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针;*/head = &a;a.next = &b;b.next = &c;c.next = NULL;p = head;//把首地址给变量do{printf("%ld %5.1f\n",p->num,p->score);//输出每个结点信息p = p->next;//使P指向下一个结点} while (p != NULL);//直到指针域指向空值return 0;
}

结果展示

在这里插入图片描述

说明

将第一个结点的起始地址赋值给头指针head,将第二个结点的起始地址赋值给第一个结点的next成员,将第二个结点的起始地址赋给第一个结点的next…第三个结点的next赋值为NULL,这就形成了简单的链表。

建立动态链表

所谓建立动态链表是指在程序执行过程中从无到有地建立起一个 链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相连的关系。

包含所需要的头文件

#include<stdio.h> //标准输入输出头文件
#include<stdlib.h>//包含了C、C++语言的最常用的系统函数
#include<malloc.h>//动态存储分配函数头文件

宏定义相关变量

#define LEN sizeof(struct Student)//宏定义节点长度得命名
#define TYPE struct Student//宏定义结构体变量命名

创建一个结构体

struct Student//定义一个学生类型结构体,包括学号,分数
{long num;float score;struct Student* next;//next是指针变量,指向结构体变量
};
//指向结构体对象得指针变量既可以指向结构体变量,也可以指向结构体数组中得元素

建立链表函数

TYPE* Creat(void)//定义函数,此函数返回一个指向链表头的指针
{TYPE* head;//定义头指针TYPE* p1,*p2;//定义两个 指针变量用来相互保存number = 0;//开始时,结点清零p1 = p2 = (TYPE*)malloc(LEN);//创建存储空间printf("请按格式输入学生学号,分数\n");//输出提示信息printf("例如101,1 并以0,0结束\n");scanf("%ld,%f", &p1->num, &p1->score);//按格式输入第一个结点的信息head = NULL;//第一个结点头指针赋空值while (p1->num!=0)//循环直到输入学生学号为0,就结束{number++;//结点自增if (number == 1)//如果只有一个结点,那么头指针指向第一个输入的结点head = p1;elsep2->next = p1;//如果大于1个,那么要用next保存前一个结点的信息p2 = p1;//保存前一个结点信息p1 = (TYPE*)malloc(LEN);//开辟新的结点scanf("%ld,%f", &p1->num, &p1->score);//输入下一个结点信息}p2->next = NULL;//循环结束,将指向信息赋空值return (head);//返回首地址
}

主函数

int main()
{TYPE* pt;//定义一个结构体指针变量pt = Creat();//函数返回链表第一个结点的地址printf("\nnum:%ld\nscore:%5.lf\n", pt->num,pt->score);//输出第一个结点的成员值return 0;
}

结果展示

在这里插入图片描述
== 文中最后结果显示的是第一个结点的内容,作为有强大功能的链表,对他的操作当然有许多,比如:链表的创建,修改,删除,插入,输出,排序,反序,清空链表的元素,求链表的长度等等。==

链表的输出

用循环直接可以输出链表

输出函数

void print(TYPE * head)
{TYPE * p;//定义指针printf("\nNOW These %d records are:\n");//输出显示信息p = head;//使p指向第一个结点if(head!=NULL)//输出第一个结点后的信息do {printf("%ld %5.1f\n",p->num,p->score);p = p->next;//指向下个结点} while (p != NULL);
}

主函数

int main()
{TYPE * pt;//定义一个结构体指针变量pt = Creat();//函数返回链表第一个结点的地址print(pt);//输出调用return 0;
}

链表的修改

修改函数

修改链表节点值很简单。下面是一个传入链表和要修改的节点,来修改值的函数.

void change(TYPE* head, int n) //修改指定位置的结点的信息
{TYPE* p = head;//传入首地址int i = 0;while (i < n && p != NULL) {p = p->next;i++;}//找到相应的位置结点if (p != NULL) {printf("输入要修改的值\n");scanf("%ld,%f", &p->num, &p->score);//输入下一个结点信息}else printf("节点不存在\n");}

主函数

int main()
{TYPE* pt;//定义一个结构体指针变量pt = Creat();//函数返回链表第一个结点的地址change(pt,2);//修改相关结点的信息,假设修改第2+1个print(pt);//输出调用return 0;
}

##链表的删除
删除链表的元素也就是把前节点的指针域越过要删除的节点指向下下个节点。即:p->next = q->next;然后放出q节点的空间,即free(q);
在这里插入图片描述

删除函数

void delet(TYPE* head, int n) {TYPE* p = head, * in;//定义两边指针int i = 0;while (i < n && p != NULL) {in = p;//找到左边的p = p->next;//找到右边的i++;}if (p != NULL) {in->next = p->next;//将左右链接free(p);//释放中间结点}else {printf("节点不存在\n");}}

主函数

int main()
{TYPE* pt;//定义一个结构体指针变量pt = Creat();//函数返回链表第一个结点的地址delet(pt,1);//删除第1+1个结点print(pt);//输出调用return 0;
}

输出结果

在这里插入图片描述
##链表的插入
我们可以看出来,插入节点就是用插入前节点的指针域链接上插入节点的数据域,再把插入节点的指针域链接上插入后节点的数据域。根据图,插入节点也就是:e->next = head->next; head->next = e;
增加链表节点用到了两个结构体指针和一个int数据。

在这里插入图片描述

插入函数

void insert(TYPE* head, int n) {//链表的插入TYPE* p = head, * in;int i = 0;while (i < n && p != NULL) {p = p->next;i++;//找到相应结点}if (p != NULL) {in = (TYPE*)malloc(sizeof(TYPE));//开辟新的空间printf("输入要插入的值\n");scanf("%ld,%f", &in->num, &in->score);//输入新的结点信息in->next = p->next;//填充in节点的指针域,也就是说把in的指针域指向p的下一个节点p->next = in;//填充p节点的指针域,把p的指针域重新指向in}else {printf("节点不存在\n");}}

主函数

int main()
{TYPE* pt;//定义一个结构体指针变量pt = Creat();//函数返回链表第一个结点的地址insert(pt, 1);//从1+1后插入print(pt);//输出调用return 0;
}

结果显示

在这里插入图片描述

出现的问题

1、出现scanf 和printf 在VS2019中使用时会出错,解决办法如下
在这里插入图片描述
在这里插入图片描述

最后是测试的所有源程序

链接: https://download.csdn.net/download/xiaoxiaodawei/12242402.


http://chatgpt.dhexx.cn/article/W7CqR3fs.shtml

相关文章

C语言链表(超详细)

前言:之前学习链表的时候总会遇到一些问题 也看了好多人的文章感觉有些不是太实用 然后后来也是自己摸索才大概写出来的. 在真正的开发中会把链表的增删改查写到函数里 但是删除有点麻烦 找了很多都是删除第几个 而不是删除某个值对应的节点 让我很难受 所以想写一些链表的…

一步一步教你从零开始写C语言链表

完整源码获取: 微信关注:嵌入式云IOT技术圈 发送"链表"即可获取。 为什么要学习链表? 链表主要有以下几大特性: 1、解决数组无法存储多种数据类型的问题。 2、解决数组中,元素个数无法改变的限制(C99的变长数组,C++也有变长数组可以实现)。 3、数组移动元…

C语言 | 链表概述

C语言链表概述 链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构&#xff0c;是根据需要开辟内存单元。 链表有一个“头指针”变量&#xff0c;它存放一个地址&#xff0c;该地址指向一个元素。 链表中每一个元素称为“结点”&#xff0c;每个结点都应包括两…

C语言链表详解(通俗易懂,超详细)

前言&#xff1a;想要很好的学好链表&#xff0c;我们首先要了解链表的优缺点&#xff08;面试&#xff09; 优点&#xff1a;1.插入 删除 不需移动其他元素, 只需改变指针&#xff1b;2:链表各个节点在内存中空间不要求连续!空间利用率高 缺点:1.访问数组元素效率低&#xf…

c语言链表详解(超详细)

链表是一种常见的基础数据结构&#xff0c;结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配&#xff0c;也就是说&#xff0c;链表是一个功能极为强大的数组&#xff0c;他可以在节点中定义多种数据类型&#xff0c;还可以根据需要随意增添&#xff0c;删除&…

【C语言】 链表 超详细解析

目录 一&#xff1a;静态存储和动态存储 二&#xff1a;存储类别 三&#xff1a;malloc函数 四&#xff1a; free函数 五&#xff1a;内存初始化函数memset 六&#xff1a;calloc函数 七&#xff1a;realloc函数 八&#xff1a;线性表 九&#xff1a;链式存储结构 …

C语言链表

C语言链表 链表的概念及结构概念结构 链表的分类单链表的实现&#xff08;无头&#xff09;双向链表的实现总结:链表和顺序表的区别 链表的概念及结构 概念 链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的…

数据结构——C语言实现链表

目录 一. 链表的概念 二. 单链表的增删查改 1.单链表的定义 2.单链表的头插与头删 3.单链表的尾插与尾删 4.单链表的中间插入删除 5.单链表的查找 三. 带头循环双向链表的增删查改 1.带头循环双向链表的定义 2.带头循环双向链表的头插与头删 3.带头循环双向链表的尾…

C语言之链表详解

目录 一、链表定义 二、链表分类 三、链表操作 四、单向链表 1.链表定义 2.插入操作 3.删除操作 4.修改操作 5.查找操作 五、双向链表 1.链表定义 2.插入操作 3.删除操作 4.修改操作 5.查找操作 一、链表定义 链表是一种基本的数据结构&#xff0c;它由一系列节…

C语言 链表创建及操作

C语言 链表创建及操作 第一部分构建链表&#xff0c;定义结构体&#xff0c;分别用头插法、尾插法实现&#xff0c;这里封装了打印函数&#xff1a;printf();做练习方便后续使用&#xff1b;对链表进行查找&#xff0c;并将查找到的值构建一个新的链表&#xff1b;链表的转置&…

Netty权威指南 读书笔记

文档太大&#xff0c;PDF格式的存档已上传到百度网盘&#xff1a; 链接: https://pan.baidu.com/s/1QnUDWujGOXXCq5iWQBIRJg 提取码: q46s

Netty权威指南(第2版) pdf百度网盘下载

欢迎大家关注我的公众号【老周聊架构】&#xff0c;Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 链接: https://pan.baidu.com/s/1DfxG9qKU2fshi6ha1a8NkA 提取码: bmt4

Netty权威指南带目录完整版.pdf

2019独角兽企业重金招聘Python工程师标准>>> Netty权威指南带目录完整版.pdf 转载于:https://my.oschina.net/xiaojianyu/blog/3011828

Netty权威指南总结(三)

五、Netty实战技巧&#xff1a; (一) 多线程编程实践&#xff1a; 1. Netty中使用多线程的技巧&#xff1a; 创建两个NioEventLoopGroup&#xff0c;用于逻辑隔离NIO Acceptor和NIO IO线程。 尽量不要在ChannelHandler中启动用户线程&#xff08;解码后用于将POJO消息派发到后端…

Netty权威指南(四)TCP粘包/拆包问题

TCP粘包/拆包问题解决之道 上一章一、介绍1.1 TCP粘包/拆包问题说明1.2 TCP粘包/拆包发生的原因1.3 粘包问题的解决策略 二、未考虑TCP粘包导致的功能异常案例2.1 TimeServerHandler的改造2.2 TimeClientHandler的改造2.3 运行 三、利用LineBasedFrameDecoder解决TCP粘包问题3.…

《Netty权威指南》

《Netty权威指南》 基本信息 作者&#xff1a; 李林锋 出版社&#xff1a;电子工业出版社 ISBN&#xff1a;9787121233432 上架时间&#xff1a;2014-5-29 出版日期&#xff1a;2014 年6月 开本&#xff1a;16开 页码&#xff1a;524 版次&#xff1a;1-1 所属分类&#xff…

Netty权威指南~第一章Java的I/O演进之路

本章内容如下&#xff1a; 5种网络I/O模型的介绍I/O多路复用的介绍 1、I/O基础入门 在Java1.4之前&#xff0c;Java对I/O的支持不完善&#xff0c;开发人员在开发高性能I/O的程序时&#xff0c;会面临以下问题&#xff1a; 没有数据缓冲区&#xff0c;I/O性能存在问题没有C…

Netty权威指南(第2版)

网站 更多书籍点击进入>> CiCi岛 下载 电子版仅供预览及学习交流使用&#xff0c;下载后请24小时内删除&#xff0c;支持正版&#xff0c;喜欢的请购买正版书籍 电子书下载(皮皮云盘-点击“普通下载”)购买正版 封页 编辑推荐 1、Hadoop、Storm、Spark、Facebook、…

Netty权威指南——WebSocket协议开发

一、简介 由于HTTP协议的开销&#xff0c;导致他们不适于用于低延迟应用&#xff0c;为了解决这些问题&#xff0c;WebSocket将网络套接字引入到了客户端和服务端&#xff0c;浏览器和服务器之间可以通过套接字建立持久的连接&#xff0c;双方随时可以互发数据给对方&#xff…

netty权威指南 微云_《Netty权威指南》(二)NIO 入门

2.1 BIO 采用 BIO 通信模型的服务器&#xff0c;通常由一个独立的 Acceptor 线程负责监听客户端的连接&#xff0c;它接收到客户端连接请求之后为每个客户端创建一个新的线程进行处理&#xff0c;处理完成后&#xff0c;通过输出流返回应答给客户端&#xff0c;线程销毁。 grap…