C语言数据结构之链表

article/2025/10/5 19:44:07

        前面的文章我们就一直说,学一个新东西之前一定要弄明白它的作用是什么,我们为什么要用它。之前讲C语言时我们讲到数组,数组的实质是一种顺序储存、随机访问、存储单元连续的线性表,既然存储单元连续,那么对其进行插入和删除操作时需要移动大量的数组元素,这时我们便需要用到链表。

        链表是由结构体和指针配合使用构成的一种动态数据结构(大家要是对C语言的指针和结构体不熟练的话可以去看看我之前的文章—嵌入式开发之C语言基础五(指针详解)和嵌入式开发之C语言基础七(结构体详解)),实质是链式存储、顺序访问的线性表,用一组任意的存储单元来存储线性表中的数据,存储单元不一定是连续的

        链表中的每个元素称为一个节点,每个节点都可以存储在内存中的不同位置,每个节点都包括两部分:第一部分为数据域,用于存储元素本身的数据信息;第二部分为指针域,其是结构体指针,用于存储其直接后继的节点信息

        创建节点和链表

创建一个结构体,其成员包括用户数据即data和用于指向下一个结构体的结构体指针*next,这里我们所说的结构体就是节点,在main函数里我们对其data进行了赋值,对next进行了下一个节点的指向,这样一个节点就创建了,通过next给链接在了一起形成了链表。 

        再通过打印函数把链表打印出来:

        既然有了链表,那么我们就可以对其进行增删查改等一系列操作:

        获得节点数

上面这段代码就获得一个链表中的节点数,逻辑应该很简单,当p != NULL时就一直遍历,同时count一直++。

         查询节点

上面这段代码就是查询一个链表中是否有某个节点,逻辑也很简单,一直遍历,同时一直与要查询的data进行判断。

         从某个节点后面插入新节点

实现插入节点功能重点就在于能否把新节点与旧节点进行链接,上面代码的实现逻辑就是:找到要被插入的节点后将其指向后一个节点的结构体指针指向要插入节点,要插入的节点再将其指向后一个节点的结构体指针指向被插入的节点原本指向的下一个的节点。这里看代码比看文字讲解要容易理解一点,大家可以多看看代码。

        从某个节点前面插入新节点

从某个节点前面插入新节点比从后面插入要多进行一次判断,判断是否为头节点,另一个要注意的地方就是while里的判断条件是用p->next来判断的,这是因为我们可以通过p来找到p的后一个,但是找不到p的前一个,所以这里我们灵活变换一下,代码实现逻辑和从后面插入大同小异。

        删除节点 

删除一个节点实现逻辑也很好理解,肯定也是要不断遍历,找到对应节点后把原本指向它的结构体指针指向它的下一个,然后按道理我们要把它free掉,但是经过测试和查找资料发现只有是malloc出来的空间才能使用free,不然运行会出现段错误

         从头插入节点

这段代码实现了从头节点开始插入新节点,所以这样出来的链表中节点的顺序要注意一下:第一个插入的节点是尾节点。 我们分析这段代码可以看到只有我们不输入0就可以不断创建新节点,而且把每个新malloc出来的新节点的next指向上一个malloc出来的节点这里要注意每次malloc一个新节点一定要把其next指向NULL,因为我之前是在虚拟机里写得代码,会默认malloc后节点的next会指向NULL,这也导致我把代码拷贝到windows中的编译器中运行会出现错误

        创建链表(头插法)

大家仔细看代码就可以发现这个所谓的创建链表就是把上段代码给拆分了,在函数creatLink中调用函数insertFromHead,当然这一定程度上是为了代码的实用性。

        创建链表(尾插法) 

上面的代码就是实现尾插法创建链表,这种方式创建出链表中节点的顺序也就是我们正常所认为的顺序,最先的就是头。和头插法不一样的是尾插法要先遍历的最后一个节点,再用最后一个节点的next指向新创建的节点 。

        以上就是数据结构中关于链表的基础知识,希望大家自己也去实现一下这几个链表功能,整个代码我会放到下面,最后希望大家学业有成,共勉。

#include <stdio.h>
#include <stdlib.h>struct Test
{int data;struct Test *next;
};void print_Link(struct Test *head)
{struct Test *p = head;while(p != NULL){printf("%d ",p->data);p = p->next;}printf("\n");
}int getNodeNum(struct Test *head)
{int count = 0;struct Test *p = head;while(p != NULL){count++;p = p->next;}return count;
}int searchLink(struct Test *head,int data)
{struct Test *p = head;while(p != NULL){if (p->data == data){return (p->data);}p = p->next;}printf("not found\n");return 0;}
struct Test* insertOneBehind(struct Test *head,int data,struct Test *new)
{struct Test *p = head;while(p != NULL){if (p->data == data){new->next = p->next;p->next = new;printf("insert ok!\n");return head;}p = p->next;}printf("insert fail\n");return head;
}struct Test* insertOneFore(struct Test *head,int data,struct Test *new)
{struct Test *p = head;if (p->data == data){new->next = p;printf("insert ok!\n");return new;}while(p->next != NULL){if (p->next->data == data){new->next = p->next;p->next = new;printf("insert ok!\n");return head;}p = p->next;}printf("insert fail\n");return head;
}struct Test* deletNode(struct Test *head,int data)
{struct Test *p = head;if (p->data == data){head = head->next;free(p);printf("delet ok!\n");return head;}while(p->next != NULL){if (p->next->data == data){	//free(p->next);p->next = p->next->next;printf("delet ok!\n");return head;}p = p->next;}printf("delet fail\n");return head;
}/*
struct Test* insertFromHead(struct Test *head)
{struct Test *new;while(1){new = (struct Test*)malloc(sizeof(struct Test));new->next = NULL;printf("please input data:\n");scanf("%d",&(new->data));if (new->data == 0){printf("quit input\n");return head;}if (head == NULL){head = new;}else{new->next = head;head = new;}}return head;
}
*/struct Test* insertFromHead(struct Test *head,struct Test *new)
{if (head == NULL){head = new;}else{new->next = head;head = new;}return head;
}struct Test* creatLink(struct Test *head)
{struct Test *new;while(1){new = (struct Test*)malloc(sizeof(struct Test));/**/new->next = NULL;printf("please input data:\n");scanf("%d",&(new->data));if (new->data == 0)	{printf("quit input\n");free(new);return head;}head = insertFromHead(head,new);}return head;
}struct Test* insertFromTail(struct Test *head,struct Test *new)
{struct Test *p = head;if (p == NULL){p = new;return p;}while(p->next != NULL){p = p->next;}p->next = new;return head;
}struct Test* creatLink2(struct Test *head)
{struct Test *new;while(1){new = (struct Test*)malloc(sizeof(struct Test));/**/new->next = NULL;printf("please input data:\n");scanf("%d",&(new->data));if (new->data == 0){printf("quit input\n");free(new);return head;}head = insertFromTail(head,new);}return head;
}int main()
{int i;int Count;int Data;int arr[3] = {1,2,3};int size = sizeof(arr)/sizeof(arr[0]); for (i = 0;i < size;i++){printf("%d ",arr[i]);}printf("\n");///*1*/struct Test t1 = {1,NULL};struct Test *p = (struct Test*)malloc(sizeof(struct Test));struct Test t2 = {2,NULL};struct Test t3 = {3,NULL};struct Test t4 = {4,NULL};p->next = &t2;p->data = 1;///*1*/t1.next = &t2;t2.next = &t3;struct Test new1 = {1000,NULL};struct Test new2 = {100,NULL};struct Test *new3 = (struct Test*)malloc(sizeof(struct Test));new3->next = NULL;new3->data = 200; struct Test *head = p;struct Test *head2 =NULL;/*1printf("link mode:\n");printf("%d %d %d\n",t1.data,t1.next->data,t1.next->next->data);print_Link(&t1);Count = getNodeNum(&t1);printf("%d\n",Count);Data = searchLink(&t1,2);printf("%d\n",Data);1*//*2head = insertOneBehind(head,1,&new1);print_Link(head);head = insertOneFore(head,3,&new2);print_Link(head);head = deletNode(head,1);print_Link(head);2*//*3head = insertFromHead(head);		//使用3功能时,把上面注释代码的注释给去掉print_Link(head);3*//*4head2 = creatLink(head2);print_Link(head2);4*//*5head2 = insertFromTail(head2,new3);print_Link(head2);5*//*6head2 = creatLink2(head2);print_Link(head2);6*/return 0;
}


http://chatgpt.dhexx.cn/article/5d8VWTlN.shtml

相关文章

C语言来实现链表创建

链表原理理解 链表作为一种线性数据&#xff0c;通过前后节点的指针指向&#xff0c;将所有数据串联起来。为了实现链表数据域的整体耦合&#xff0c;需要额外的指针域来标定前后数据的连接。通过下面的链表结构图&#xff0c;可以非常容易的理解链表的组成结构 头节点作为链表…

链表C语言和C++两种方式实现

一、C语言版本链表&#xff1a; 方向1&#xff1a;无表头 法一&#xff1a;尾插法 #include<stdio.h> #include<malloc.h> //打印 创建 释放 删除某个数 插入某个数 &#xff08;T_T&#xff09;5个功能 struct Node {int data;struct Node* next; }; typedef st…

C语言实现链表创建

C语言实现链表的创建 链表:是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点链表中每一个元素称为结点&#xff09;组成&#xff0c;结点可以在运行时动态生成。每个结点包括两个部分&#xf…

链表(c语言实现)

1.链表的分类 实际中链表的结构非常多样&#xff0c;以下情况组合起来就有8种链表结构&#xff1a; &#xff08;1&#xff09;单向或者双向 &#xff08;2&#xff09;带头或者不带头 &#xff08;3&#xff09;循环或者非循环 虽然有这么多的链表的结构&#xff0c;但是我们…

用c语言写链表

链表是数据结构的一种&#xff0c;是其他三个数据结构栈&#xff0c;树&#xff0c;图的基础&#xff0c;只有将链表这一数据结构弄懂&#xff0c;才能理解其他三种数据结构。 举一个例子&#xff0c;老师让你设计一个联系人系统&#xff0c;其中包括姓名&#xff0c;电话号&am…

C语言链表超详解

✅作者简介&#xff1a;嵌入式入坑者&#xff0c;与大家一起加油&#xff0c;希望文章能够帮助各位&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4c3;个人主页&#xff1a;rivencode的个人主页 &#x1f525;系列专栏&#xff1a;玩转数据结构 &#x1f4ac;保持…

C语言——链表简单介绍

一、链表的引入 我们至少可以通过两种结构存储数据。 数组&#xff1a;数组是一个固定长度的存储相同数据类型的数据结构&#xff0c;数组中的元素被存储在一段连续的内存空间中。 优点&#xff1a;存取速度快。 缺点&#xff1a;需要一个连续的很大的内存&#xff1b; 插入和…

c语言链表示例

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

反转链表c语言

反转链表 初始化三个指针 循环执行 temp cur→next cur→next pre pre cur ; cur temp 对于单链表&#xff0c;所有操作都是从头指针开始 // An highlighted block struct ListNode* ReverseList(struct ListNode* pHead ) {// 三指针法struct ListNode* pre pHead;s…

链表C语言实现--单向链表

线性结构的链式存储也称为链表&#xff0c;相比于顺序表&#xff0c;链表能够解决顺序表中空间资源浪费问题以及空间不足的问题。链表的每一个结点包含数据域和指针域&#xff0c;而每一个结点在内存中的地址是不连续的&#xff0c;且能适应动态变化。在数据插入和数据删除操作…

循环链表C语言实现

本文介绍循环链表中的单向循环链表&#xff0c;双向循环链表两种 第一种&#xff1a;单向循环链表&#xff0c;是在单向链表的基础上&#xff0c;尾结点不再指向NULL&#xff0c;而是指向头结点从而构成循环。如下图&#xff1a; 所以相比单向链表最大的特点就是可以从尾快速循…

C语言基础入门:链表详解篇

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

C语言——基础链表详解

敢于向黑暗宣战的人&#xff0c;心里必须充满光明。 一、链表的构成 1.构成 链表是由一连串的结构&#xff08;称为结点&#xff09;组成的。 (1)结点的构成&#xff1a; 数据&#xff08;要储存的数据&#xff09;指针&#xff08;指向下一个结点的指针&#xff09; (2)关…

C语言数据结构——链表

目录 前言 一、什么是链表 1.1链表的结构和概念 1.2 链表的分类 二、无头单向非循环链表 2.1 创建结构体 2.2 动态申请一个节点 2.3 单链表打印 2.4 单链表尾插/尾删 2.4.1 单链表尾插 2.4.2 单链表尾删 2.5 单链表头插/头删 2.5.1 头插 2.5.2 头删 2.6 单链表查…

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

文章目录 前言一、什么是线性表&#xff1f;二、顺序表&#xff1a;三、链表&#xff1a;四、顺序表和链表对比&#xff1a;总结 前言 线性表是实际中广泛应用的重要数据结构&#xff0c;本文用通俗易懂的方法讲解它。 一、什么是线性表&#xff1f; 首先&#xff0c;我们了解…

C语言——链表

C语言——链表 链表是一种基础的数据结构类型&#xff0c;一种能够动态维护数据的线性数据表。链表的数据以结点形式存储信息&#xff0c;并通过结点之间的指针实现结点之间的衔接。 为什么要用链表&#xff1f; 链表和数组类似&#xff0c;但是功能比数组强大得多&#xff0c…

在?您的rsyslog日志管理手册到了,请查收

rsyslog日志管理和logrotate日志存储轮转 前言&#xff1a; 系统日志是记录服务器系统运行和软件运行状况的记录程序&#xff0c;如果系统和软件在运行中出错&#xff0c;我们就可以在日志中获取到问题发生时的记录&#xff0c;并以此寻求解决问题的方法。 一.rsyslog 系统日…

日志审计与分析实验三(rsyslog服务器端和客户端配置)(Linux日志收集)

文章目录 Linux日志收集一、实验目的&#xff1a;1、掌握rsyslog配置方法2、配置rsyslog服务收集其他Linux服务器日志: 二、实验步骤&#xff1a;1、前期配置2. rsyslog的三种传输协议1、udp传输方式2、tcp传输方式3、relp传输方式 Linux日志收集 一、实验目的&#xff1a; 1…

Linux系统之rsyslog配置

目录 Rsyslog简介 Linux配置rsyslog 配置实验&#xff1a; 实验环境&#xff1a; 实验步骤&#xff1a; 实验准备&#xff1a; 针对UDP&#xff1a; 针对TCP&#xff1a; 针对RELP&#xff1a; 结果验证&#xff1a; 1、UDP&#xff1a; 2、TCP&#xff1a; 3、RE…

rSyslog日志

日志服务管理 系统日志管理 系统日志介绍 日志的作用&#xff1a; 软件的运行记录软件运行排错运行分析 日志记录的内容包括&#xff1a; 历史事件&#xff1a;时间&#xff0c;地点&#xff0c;人物&#xff0c;事件日志级别&#xff1a;事件的关键性程度&#xff0c;Lo…