链表(c语言实现)

article/2025/10/5 19:37:40

1.链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

(1)单向或者双向


(2)带头或者不带头


(3)循环或者非循环

 虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

 1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。

2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。

2.无头单向非循环链表的实现

// 1、无头+单向+非循环链表增删查改实现
typedef int SLTDateType;
typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SListNode;// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);
// 1、无头+单向+非循环链表增删查改实现
SListNode* BuySListNode(SLTDateType x)
{SListNode* tmp = (SListNode*)malloc(sizeof(SListNode));if (tmp == NULL){printf("无法给节点开辟空间\n");return NULL;}else{tmp->data = x;tmp->next = NULL;return tmp;}
}
// 单链表打印
void SListPrint(SListNode* plist)
{SListNode* head = plist;while (head != NULL){printf("%d ", head->data);head = head->next;}
}
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if ( *pplist== NULL){*pplist = newnode;}else{SListNode* tail = *pplist;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}
// 单链表的尾删
void SListPopBack(SListNode** pplist)
{assert(*pplist);SListNode* cur = *pplist;SListNode* prev = NULL;if (cur->next == NULL){free(cur);*pplist = NULL;}else{while (cur->next != NULL){prev = cur;cur = cur->next;}free(cur);prev->next = NULL;}
}
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{SListNode* newnode = BuySListNode(x);if (*pplist == NULL){*pplist = newnode;}else{newnode->next = *pplist;*pplist = newnode;}
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{assert(*pplist);SListNode* cur = *pplist;if ((*pplist)->next == NULL){free(*pplist);*pplist = NULL;}else{cur = cur->next;free(*pplist);*pplist = cur;}
}
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{assert(plist);while (plist != NULL){if (plist->data == x){return plist;}plist = plist->next;}return NULL;
}
// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLTDateType x)
{assert(pos);SListNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{assert(pos);if (pos->next == NULL){printf("后面无数据\n");return;}else{SListNode* prev = pos;SListNode* cur = pos->next;prev->next = cur->next;free(cur);cur = NULL;}}

3. 带头双向循环链表

// 2、带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode 
{ListDateType val;struct ListNode* prev;struct ListNode* next;
}ListNode;	//初始化双向链表
ListNode* ListInit(ListNode* phead);
//双向链表打印
void ListPrint(ListNode* phead);
// 创建返回链表的头结点.
ListNode* BuyList(ListDateType x);
//双向链表尾插
void ListPushBack(ListNode* phead,ListDateType x);
//双向链表尾删
void ListPopBack(ListNode* phead);
//双向链表头插
void ListPushFront(ListNode* phead, ListDateType x);
//双向链表头删
void ListPopFront(ListNode* phead);
//双向链表查找
ListNode* ListFind(ListNode* pHead, ListDateType x);
//在pos之前插入
void ListInsert(ListNode* pos, ListDateType x);
//删除pos位置
void ListErase(ListNode* pos);
//初始化双向链表
ListNode* ListInit(ListNode* phead)
{phead = BuyList(0);phead->next = phead;phead->prev = phead;return phead;
}
//双向链表打印
void ListPrint(ListNode* phead)
{ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->val);cur = cur->next;}}
// 创建返回链表的头结点
ListNode* BuyList(ListDateType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){printf("BuyList fail\n");exit(-1);}newnode->val = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}
//双向链表尾插
void ListPushBack(ListNode* phead, ListDateType x)
{assert(phead);ListNode* newnode = BuyList(x);ListNode* tail = phead->prev;tail->next = newnode;phead->prev = newnode;newnode->next = phead;newnode->prev = tail;
}
//双向链表尾删
void ListPopBack(ListNode* phead)
{assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* prev = tail->prev;phead->prev = prev;prev->next = phead;free(tail);tail = NULL;
}
//双向链表头插
void ListPushFront(ListNode* phead, ListDateType x)
{assert(phead);ListNode* newnode = BuyList(x);ListNode* head = phead->next;phead->next = newnode;head->prev = newnode;newnode->next = head;newnode->prev = phead;
}
//双向链表头删
void ListPopFront(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* head = phead->next;ListNode* next = head->next;phead->next = next;next->prev = phead;free(head);head = NULL;
}
//双向链表查找
ListNode* ListFind(ListNode* phead, ListDateType x)
{assert(phead);assert(phead->next != phead);ListNode* pos = phead->next;while (pos != phead){if (pos->val == x){return pos;}pos = pos->next;}return NULL;
}
//在pos之前插入
void ListInsert(ListNode* pos, ListDateType x)
{assert(pos);ListNode* newnode = BuyList(x);ListNode* prev = pos->prev;prev->next = newnode;pos->prev = newnode;newnode->prev = prev;newnode->next = pos;
}
//删除pos位置
void ListErase(ListNode* pos)
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}


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

相关文章

用c语言写链表

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

C语言链表超详解

✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!! 📃个人主页:rivencode的个人主页 🔥系列专栏:玩转数据结构 💬保持…

C语言——链表简单介绍

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

c语言链表示例

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

反转链表c语言

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

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

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

循环链表C语言实现

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

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

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

C语言——基础链表详解

敢于向黑暗宣战的人,心里必须充满光明。 一、链表的构成 1.构成 链表是由一连串的结构(称为结点)组成的。 (1)结点的构成: 数据(要储存的数据)指针(指向下一个结点的指针) (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语言链表详解(通俗易懂)

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

C语言——链表

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

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

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

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

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

Linux系统之rsyslog配置

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

rSyslog日志

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

Linux rsyslog详细介绍

转自:http://llei623.blog.163.com/blog/static/852075042010111482731766/ 作者:llei WEB服务器多的时候检查日志是一件痛苦的事情,用 perl 脚本登录到服务器上grep一些错误信息两次之后就觉得是纯体力活,想办法偷懒。 准备弄…

Linux系统日志rsyslogd

Linux系统日志rsyslogd Linux系统日志 Linux上使用rsyslogd守护进程接收用户进程输出的日志和接收内核日志。 用户进程是通过syslogd函数生成系统日志。该函数将日志输出到一个UNIX本地域socket类型(AF_UNIX)的文件/dev/log中,rsyslogd则监听该文件以…

Linux之 rsyslog、日志轮转

1.rsyslog 1.1rsyslog介绍 Rsyslog的全称是 rocket-fast system for log,它提供了高性能,高安全功能和模块化设计。rsyslog能够接受从各种各样的来源,将其输入,输出的结果到不同的目的地。rsyslog可以提供超过每秒一百万条消息给…

rsyslog日志服务简介

1、简介 rsyslog是一个linux系统日志服务的工具,主要用来监控收集系统从开机运行之后所发生的所有日志,包括内核日志,服务日志,应用日志等等;记录的日志全部都写到/var/log下面,常用的有dmsg(内…