循环链表C语言实现

article/2025/10/5 22:11:14

本文介绍循环链表中的单向循环链表,双向循环链表两种

第一种:单向循环链表,是在单向链表的基础上,尾结点不再指向NULL,而是指向头结点从而构成循环。如下图:

 所以相比单向链表最大的特点就是可以从尾快速循环到头,这样从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现。

注:单向链表的介绍和C语言实现可参考我另一篇文章,链表C语言实现--单向链表_into the unknown-的博客-CSDN博客

结点结构体不变,而在创建头结点和其他结点时可初始化指针域next指向头结点。

具体代码如下:

typedef int data_t;
typedef struct linklist
{data_t data;//数据域struct linklist *next;//指针域
}LinkList;

创捷头结点:

LinkList *Creat_Linklist()
{LinkList *head=(LinkList*)malloc(sizeof(LinkList));if(NULL==head){printf("malloc error!\n");return NULL;}head->data=-1;head->next=head;return head;
}

头插法添加数据和单向链表一样:

void Linklist_Insert_head(LinkList *h_node,data_t data)
{LinkList *p=(LinkList *)malloc(sizeof(LinkList));if(NULL==p){printf("malloc new node error!\n");return ;}p->data=data;//存数据p->next=h_node->next;//新节点拿到下一节点的地址h_node->next=p; //上一节点刷新得到新节点的地址
}

与单向链表的不同之一就是遍历链表的终止条件是结点的next指向了头结点,如下面的链表判空、打印链表等。

int Linklist_Is_Empty(LinkList *h_node)
{if(h_node->next==h_node)return 0;//表空返回0else return 1;
}
void Linklist_Show(LinkList *h_node)
{if(Linklist_Is_Empty(h_node)==0){printf("表为空,无法打印\n");return ;}LinkList *p=h_node->next;//p指向头节点后的第一个节点while(p!=h_head){printf("%d,",p->data);//打印数据p=p->next;}
}

后续链表的按位置插入,删除、查找等操作和单链表基本一样,只是链表遍历的条件变成p!=h_node,所以不再展示,下面展示两个单向循环链表的链表合并成一个链表的操作

两个单向循环链表的连接:void lianjie(LinkList *linka,LinkList *linkb)
{LinkList *p,*q,*r;p=linka->next;q=linkb->next;r=NULL;while(p->next!=linka){p=p->next;}while(q->next!=linkb){q=q->next;}p->next=linkb->next;q->next=linka;linkb->next=linkb;
}

第二种:双向循环链表

也是在双向链表基础上进行改进,也就是尾结点next指针指向头结点,头结点prior指针指向尾结点

如下图:

 具体代码如下:

/*===============================================
*   文件名称:lib.h
*   创 建 者:xm     
*   创建日期:2022年07月29日
*   描    述:
================================================*/
#ifndef _LIB_
#define _LIB_
#include <stdio.h>
#include <stdlib.h>typedef int data_t;
typedef struct d_node
{data_t data;//数据域struct d_node *next;//指针域struct d_node *prior;
}DLinkList;//创建头节点
DLinkList *Creat_DLinklist();
//判空
int DLinklist_Is_Empty(DLinkList *head);
//求表长
int DLinklist_length(DLinkList *head);
//头插法
void DLinklist_Insert_head(DLinkList *head,data_t data);
//打印
void DLinklist_Show(DLinkList *head);
//按位置插入数据
void DLinklist_Insert_Pos(DLinkList *head,int pos,data_t data);
//按位置删除
void DLinklist_Delete_Pos(DLinkList *head,int pos);#endif

功能模块:

/*===============================================
*   文件名称:dnode.c
*   创 建 者:xm     
*   创建日期:2022年07月29日
*   描    述:
================================================*/
#include "lib.h"DLinkList *Creat_DLinklist()
{DLinkList *head=(DLinkList *)malloc(sizeof(DLinkList));if(NULL==head){puts("malloc error!");return NULL;}head->data=-1;head->next=head;head->prior=head;
}
//头插法
void DLinklist_Insert_head(DLinkList *head,data_t data)
{DLinkList *new=(DLinkList *)malloc(sizeof(DLinkList));if(NULL==new){puts("malloc error!");return ;}new->data=data;new->next=head->next;head->next->prior=new;//这条语句和下面那条语句必须要在下下面那条语句先执行,才不会打乱连接。在改原下一节点时不能动头节点的指向。new->prior=head;//总结就是前插,先操作原后一节点,再操作前一节点的连接。head->next=new;}
//打印表
void DLinklist_Show(DLinkList *head)
{DLinkList *p=head->next;while(p!=head){printf("%d,",p->data);p=p->next;}
}
//判空
int DLinklist_Is_Empty(DLinkList *head)
{if(head->next==head && head->prior==head)return 0;else return 1;
}
//求表长
int DLinklist_length(DLinkList *head)
{DLinkList *p=head->next;int len=0;while(p!=head){len++;p=p->next;}return len;
}
//按位置插入数据,位置从1开始
void DLinklist_Insert_Pos(DLinkList *head,int pos,data_t data)
{if(pos<=0||pos>(DLinklist_length(head)+1)){printf("位置错误\n");return ;}DLinkList *new=(DLinkList *)malloc(sizeof(DLinkList));if(NULL==new){puts("malloc error!");return ;}DLinkList *n=head;pos--;while(pos--){n=n->next;}new->data=data;new->next=n->next;n->next->prior=new;new->prior=n;n->next=new;
}
//按位置删除,位置从1计数
void DLinklist_Delete_Pos(DLinkList *head,int pos)
{if(pos<=0||pos>(DLinklist_length(head)+1)){printf("位置错误\n");return ;}DLinkList *p=head;while(pos--){p=p->next;}p->prior->next=p->next;p->next->prior=p->prior;free(p);p=NULL;
}

主函数测试:

/*===============================================
*   文件名称:main.c
*   创 建 者: xm    
*   创建日期:2022年07月29日
*   描    述:
================================================*/
#include <stdio.h>
#include "lib.h"
int main(int argc, char *argv[])
{ DLinkList *head=Creat_DLinklist();if(DLinklist_Is_Empty(head)==0)puts("表为空");else puts("表非空");int n=10;while(n--){DLinklist_Insert_head(head,n);}DLinklist_Show(head);if(DLinklist_Is_Empty(head)==0)puts("表为空");else puts("表非空");int len=DLinklist_length(head);printf("len=%d\n",len);DLinklist_Insert_Pos(head,2,888);//插入的位置从1计数DLinklist_Show(head);DLinklist_Delete_Pos(head,5);puts("删除后");DLinklist_Show(head);return 0;
} 

双向循环链表在数据查找和修改上相比单链表效率有所提升,且可以在链表中任意一个节点,快速访问到其他节点。


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

相关文章

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…

Linux rsyslog详细介绍

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

Linux系统日志rsyslogd

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

Linux之 rsyslog、日志轮转

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

rsyslog日志服务简介

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

Linux 日志管理 Rsyslog Loganalyzer

Syslog常被称为系统日志或系统记录&#xff0c;是一种用来在互联网协议&#xff08;TCP/IP&#xff09;的网上中传递记录档消息的标准。这个词汇常用来指涉实际的syslog 协议&#xff0c;或者那些提交syslog消息的应用程序或数据库。 syslog协议属于一种主从式协议&#xff1a…

建立 rsyslog 日志服务器

文章目录 1. rsyslog 介绍2. 实验目的3. 实验环境4. 配置服务端5. 配置客户端6. 在服务端验证效果 1. rsyslog 介绍 rsyslog 是一个快速处理收集系统日志的开源程序&#xff0c;提供了高性能、安全功能和模块化设计。rsyslog 是 syslog 的升级版&#xff0c;它将多种来源输入输…

rsyslog配置

rsyslog配置文件详解&#xff1a; #### MODULES #### #定义日志的模块。 $ModLoad imuxsock #imuxsock为模块名&#xff0c;支持本地系统日志的模块。 $ModLoad imjournal #imjournal为模块名&#xff0c;支持对系统日志的访问。 #$ModLo…

syslog 和 rsyslog

1. 介绍 rsyslog可以简单的理解为syslog的超集&#xff0c;在老版本的Linux系统中&#xff0c;Red Hat Enterprise Linux 3/4/5默认是使用的syslog作为系统的日志工具&#xff0c;从RHEL 6 开始系统默认使用了rsyslog。 其特性包括&#xff1a; 支持输出日志到各种数据库&…

rsyslog日志服务详解

rsyslog日志服务详解 原文出处&#xff1a;http://blog.51cto.com/6638225/1862902 内容&#xff1a; 1、rsyslog日志服务简介 2、rsyslog的配置详解 3、实现日志服务器收集日志及last、lastb、dmseg命令的使用 4、实现日志存储在mysql中 一、rsyslog日志服务简介 ​ 日…

【Linux】rsyslog日志服务(配置,测试、日志转储)

一、rsyslog简介 Rsyslog的全称是 rocket-fast system for log ,可用于接受来自各种来源的输入&#xff0c;转换 它们&#xff0c;并将结果输出到不同的目的地。 它提供了高性能、强大的安全功能和模块化设计。虽然rsyslog最初是一个常规的系 统日志&#xff0c;但它已经发展…

Linux原生日志系统Rsyslog详解

一、概述 Rsyslog 是一个 syslogd 的多线程增强版&#xff0c;依然基于Syslog协议&#xff08;linux6之前默认使用syslog程序&#xff0c;centos6用rsyslog所取代&#xff09;完成系统日志的处理转发&#xff0c;官方形容它是一个极速&#xff08;如火箭般快速&#xff09;的日…