C语言中的链表

article/2025/9/14 12:05:51

目录

一、链表概述

二、链表操作

1、动态创建链表

(1)malloc函数

(2)calloc函数

(3)free函数

2、链表的插入操作

3、链表的删除操作补充内容

三、链表完整代码实现


一、链表概述

        链表是一种常见的数据结构,在链表中可以动态的进行内存分配。也可以将链表看成是一个功能强大的数组,它可以在节点中定义多种数据类型,还可以根据需要随意增加,删除,或者插入节点。

        每个链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。

        简单来说,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,最后的一个元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。

        本文仅对单链表进行介绍。

 

二、链表操作

1、动态创建链表

        链表的创建的是一个动态的过程,动态创建一个节点时,要为其分配内存,相关函数介绍如下:

(1)malloc函数

        函数功能:在内存中动态地分配一块size大小的内存空间。malloc函数会返回一个指针,该指针指向分配的内存空间,如果出现错误则返回NULL。

        malloc函数原型如下:

void *malloc(unsigned int size);

(2)calloc函数

        函数功能:在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址。当分配空间错误时,返回NULL。

        calloc函数原型如下:

void *calloc(unsigned n, unsigned size);

(3)free函数

        函数功能:使用由指针ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。(释放内存空间)

        函数原型如下:

void free(void *ptr);

2、链表的插入操作

        链表的插入操作可以在链表的头节点位置进行,也可以在中间节点或者尾结点进行。三种链表的插入操作思路是一样的。

// 链表的插入操作(在链表的头结点插入)
// 该函数将会返回链表的头指针
struct Student *Insert(struct Student *pHead)
{struct Student *pNew;                   // 指向新分配的空间printf("-------Insert member at first------\n");        // 提示信息pNew = (struct Student*)malloc(sizeof(struct Student));  // 分配内存空间,并返回指向该内存空间的指针scanf("%s",&pNew->cName);               // 输入新加入的学生姓名scanf("%d",&pNew->iNumber);             // 输入新加入的学生学号// 两步操作:1.将原来的头节点地址给到新节点指向的下一级节点;2.将新节点的地址给到头节点。pNew->pNext = pHead;                    // 新节点指针指向原来的首节点(将原来的头结点地址给到新加入的节点指向的地址)pHead = pNew;                           // 链表头指针指向新节点(新节点变成了头节点)iCount++;                               // 增加链表的节点数return pHead;                           // 返回链表头指针
}

3、链表的删除操作补充内容

        链表删除过程中,可以对待删除的链表序号进行判断

(1)在对头结点进行赋值过程中,可以先对链表的头结点进行判断,判断当前链表头节点是否为空, 非空情况下再进行后续的头结点赋值操作;

    if (pHead == NULL)                              // 首先判断链表头是否为空,即整个链表是否为空表{                                               // 若是空表,则输出空printf("\n---The List NULL!---\n");return pHead;}pTemp = pHead;                                  // pHead赋值给pTemp,得到链表的头结点

(2)在执行循环判断语句过程中,可以先判断待删除的节点下标序号是否为pTemp指向的节点;

	while ((iIndex != pTemp->iIndex) && (pTemp->pNext != NULL))     // 当要删除的iIndex不等于pTemp所指向的节点下标且满足pTemp的下一个结点不为空{pPre = pTemp;                               // 将pTemp赋给pPre;pTemp = pTemp->pNext;                       // 再将pTemp指向下一个节点;重复进行,直到找到待删除的节点序号,此时pTemp指向的节点就是所要找的待删除节点}

(3)在进行节点删除过程中,可以先判断待删除的节点是否为第一个节点;

	if (iIndex == pTemp->iIndex) {                          // 除非链表中不存在要寻找的iIndex,否则这个条件是一定成立的,if(pTemp == pHead){                                           // 如果要删除的是第1个节点pHead = pTemp->pNext;                   // 则让pHead指向pTemp的下一个节点,也就是第二个节点}else {pPre->pNext = pTemp->pNext;             // 如果要删除的不是第一个节点,则让pPre的next指向pTemp(要删除的结点)的下一个结点,此时则跳过了这个iIndex,即达到删除的效果}printf("Delete: %d\n", iIndex);iCount = iCount - 1;}

三、链表完整代码实现

        本节详细链表操作见代码实现,包括链表的动态创建,插入、删除和输出操作。

#include<stdio.h>
#include<stdlib.h>// 创建链表节点结构,表示每一个学生
struct Student
{char cName[20];             // 学生姓名int iNumber;                // 学号struct Student *pNext;      // 指向下一个节点的指针
};int iCount;                     // 全局变量表示链表长度// Create函数的功能是创建链表,动态分配内存空间的方式创建链表
// 该函数将会返回链表的头指针
//(在链表的尾结点插入)
struct Student *Create()
{struct Student *pHead = NULL;           // 初始换链表头指针为空struct Student *pNew, *pEnd;            // pEnd用来指向原来的尾节点,pNew用来指向新创建的节点iCount = 0;                             // 表示链表中节点的数量pEnd = pNew = (struct Student*)malloc(sizeof(struct Student));     // malloc 函数分配内存,先用pEnd和pNew两个指针都指向第一个分配的内存printf("------Please First Enter Name, The Number------\n");scanf("%s",&pNew->cName);scanf("%d",&pNew->iNumber);while(pNew->iNumber != 0){iCount++;// 第一次加入节点,新节点即为首节点,也是最后一个节点,并且需要将新加入的节点的指针指向NULL,即为pHead指向。if(iCount == 1){pNew->pNext = pHead;            // 使得指针指向为空(新加入的节点为首节点的时候,节点空指针即为pHead指向pEnd = pNew;                    // 跟踪新加入的节点(新加入的节点地址即为尾结点地址)pHead = pNew;                   // 头指针指向首节点(将新加入的节点的地址给头指针)}else{pNew->pNext = NULL;             // 新节点的指针为空(将新加入的节点指针指向空)pEnd->pNext = pNew;             // 原来的尾结点指向新节点(原来的尾结点变成了中间节点,需要将新节点地址给原来的尾结点)pEnd = pNew;                    // pEnd指向新节点(让新加入的节点成为尾结点)}pNew = (struct Student*)malloc(sizeof(struct Student));      // 再次分配节点内存空间scanf("%s",&pNew->cName);           // 再次输入新的节点进入循环判断,如果满足新节点要求则执行循环继续添加,如果不满足则跳出循环scanf("%d",&pNew->iNumber);}free(pNew);                             // 不满足新节点要求,跳出循环后调用free函数释放未使用的内存空间return pHead;                           // 该函数返回链表的头指针
}// 定义打印函数Print
// void 函数没有返回值
void Print(struct Student *pHead)
{struct Student *pTemp;                  // 循环所用的临时指针int iIndex = 1;                         // 表示链表中节点的序号printf("======The List Has %d Members:======\n",iCount);printf("\n");pTemp = pHead;                          // 指针得到首节点的地址while(pTemp != NULL){printf("The NO%d Member is:\n",iIndex);printf("The Name is %s\n",pTemp->cName);            // 输出姓名printf("The Number is %d\n",pTemp->iNumber);        // 输出学号printf("\n");pTemp = pTemp->pNext;                               // 移动临时指针到下一个节点iIndex++;                                           // 进行自加运算}
}// 链表的插入操作(在链表的头结点插入)
// 该函数将会返回链表的头指针
struct Student *Insert(struct Student *pHead)
{struct Student *pNew;                   // 指向新分配的空间printf("-------Insert member at first------\n");        // 提示信息pNew = (struct Student*)malloc(sizeof(struct Student));  // 分配内存空间,并返回指向该内存空间的指针scanf("%s",&pNew->cName);               // 输入新加入的学生姓名scanf("%d",&pNew->iNumber);             // 输入新加入的学生学号// 两步操作:1.将原来的头节点地址给到新节点指向的下一级节点;2.将新节点的地址给到头节点。pNew->pNext = pHead;                    // 新节点指针指向原来的首节点(将原来的头结点地址给到新加入的节点指向的地址)pHead = pNew;                           // 链表头指针指向新节点(新节点变成了头节点)iCount++;                               // 增加链表的节点数return pHead;                           // 返回链表头指针
}// 删除链表节点
// 输入:链表头结点pHead,要删除的节点下标iIndex;dd
void Delete(struct Student *pHead, int iIndex)
{int i;                                  // 控制循环变量struct Student *pTemp;                  // 临时指针变量,表示要删除的节点struct Student *pPre;                   // 表示要删除节点之前 的节点pTemp = pHead;                          // pHead赋值给pTemp,得到链表的头结点pPre = pTemp;                           // pPre指向pTemp,将pTemp的地址给到pPreprintf("======Delete NO%d member======\n",iIndex);          // 提示待删除节点位置信息// for语句进行循环操作,使得pTemp指向要删除的节点for(i=1; 1<iIndex; i++){// 将pTemp赋值给pPre,再将pTemp指向下一个节点,重复进行,直到找到需要定位的iIndex节点,此时pTemp指向的节点就是所要找的待删除的节点pPre = pTemp;                       // 定位到要删除的节点pTemppTemp = pTemp->pNext;               // 再将pTemp指向下一个节点}pPre->pNext = pTemp->pNext;             // 连接待删除节点两边的节点地址(将待删除节点两边的地址相关联)(重点!!!)free(pTemp);                            // 释放掉要删除节点的内存空间iCount--;                               // 减少链表中元素的个数
}// 定义主函数
int main()
{struct Student *pHead;                  // 定义头结点pHead = Create();                       // 创建链表节点pHead = Insert(pHead);                  // 插入新的节点Delete(pHead,2);                        // 删除链表中第二个节点的操作Print(pHead);                           // 输出最终的链表return 0;
}


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

相关文章

C语言链表详解附实例

C语言链表详解附实例 什么是链表 链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。链表和数组比较&#xff0c;不用事先确定存储空间&#xff0c;而是根据需要开辟内存单元。 下图1是最简单的一种链表&#xff08;单向链表&#xff09;的结构 第 0 个结…

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…