C语言数据结构循环链表

循环链表的定义

循环链表是一种链表数据结构,与标准链表不同之处在于,循环链表的最后一个节点指向第一个节点,形成一个环状结构。

循环链表通常包括结点、头指针,以及循环特性。在遍历时,可以持续前进直到访问完所有节点。这种结构常用于需要循环遍历一组数据的情况,如循环队列或循环播放列表。在代码中,要确保节点和头指针正确连接以形成循环。

循环链表的特点

  1. 环状结构:最后一个节点指向第一个节点,形成一个环,可无限循环遍历。

  2. 动态扩展:适用于动态大小需求,不限制链表长度。

  3. 循环遍历便利:遍历操作方便,无需终止点。

  4. 插入和删除复杂:插入和删除节点需小心操作,牵涉前一节点指针的调整

循环链表的运算 

  1. 初始化:创建一个空的循环链表,通常将头指针指向NULL。

  2. 插入:在链表中插入新节点,可以是在链表头部、尾部或指定位置插入。插入操作需要考虑前一节点的指针调整,以保持环状结构。

  3. 删除:从链表中删除指定节点。删除操作也需要考虑前一节点的指针调整,以确保环状结构的完整性。

  4. 遍历:从头节点开始沿着"下一个"指针遍历整个链表,直到回到头节点为止。这使得可以循环遍历链表中的所有节点。

  5. 查找:查找链表中的特定节点,可以是根据节点值或位置查找。

  6. 判断空和满:检查循环链表是否为空或已满。

  7. 扩容:如果链表支持动态大小,可以实现扩容操作,以增加链表的容量。

循环链表的实现

定义链表

typedef int DataType;

/*简单链表的定义*/
typedef struct node
{
	DataType		data;	/*数据域*/
	struct node		*next;	/*指针域*/
}SingleLinkList, SingleLinkNode;

初始化链表

/*1. 初始化*/
int init(SingleLinkList **Head)
{
	if(1)
	{
		/*申请内存*/
		(*Head) = (SingleLinkList*)malloc(sizeof(SingleLinkList));
		/*判断内存申请是否成功*/
		if(*Head == NULL)
		{
			printf("申请内存错误, 初始化失败![100001]\n");
			return 100001;
		}
		(*Head)->next = *Head;
		/*循环链表*/
		/*
			(*Head)->next = *Head;
		*/
		return 0;
	}
	else
	{
		printf("该链表已经初始化!请删除后再执行此操作![100002]\n");
		return 100002;
	}
}

插入元素

/*2. 插入元素,头插法*/
int insert_head(SingleLinkList **Head, DataType x)
{
	SingleLinkNode *newNode;

	if(0)
	{
		printf("链表未初始化![100003]\n");
		return 100003;
	}
	
	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	if(!newNode)
	{
		printf("申请节点内存空间失败![100004]\n");
		return 100004;
	}
	newNode->data = x;
	newNode->next = (*Head)->next;

	(*Head)->next = newNode;

	return 0;
}


/*2. 插入元素, 尾插法*/
int insert_tail(SingleLinkList **Head, DataType x)
{
	SingleLinkNode *newNode;
	SingleLinkNode *p;

	if(0)
	{
		printf("链表未初始化![100003]\n");
		return 100003;
	}
	
	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	if(!newNode)
	{
		printf("申请节点内存空间失败![100004]\n");
		return 100004;
	}

	newNode->data = x;
	newNode->next = *Head;
	/*
	  循环链表
	  newNode->next = *Head;
	*/

	p = (*Head);

	while(p->next!=*Head)
	{
		p = p->next;
	}

	p->next = newNode;

	return 0;
}


/*2. 插入元素,在位置i处插入元素x */
int insert(SingleLinkList **Head, int i, DataType x)
{
	int j;
	SingleLinkNode *p;
	SingleLinkNode *newNode;

	
	/*对i进行判断,0<i<=length+1*/
	if(i<1 || i>length(*Head)+1)
	{
		printf("位置i不是链表有效位置![100005]\n");
		return 100005;
	}
	p = (*Head);
	j = 1;

	while(j<i)
	{
		j++;
		p = p->next;
	}

	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	/*此处省略检测newNode是否申请成功*/

	newNode->data = x;
	newNode->next = p->next;
	p->next = newNode;
	return 0;
}

删除元素

int delete(SingleLinkList **Head, DataType x)
{
	int i;
	int j;

	SingleLinkNode *p;
	SingleLinkNode *q; /*要删除的元素x*/

	i = find(*Head,x);
	if(!i)
	{
		printf("元素x【%d】不存在!100006\n", x);
		return 100006;
	}
	
	p = (*Head);
	j=1;

	while(j<i)
	{
		j++;
		p = p->next;
	}
	
	q = p->next;
	p->next = q->next;

	free(q); /*释放内存*/

	return 0;
}

 查找元素

int find(SingleLinkList *Head, DataType x)
{
	int i;
	SingleLinkNode *p;

	i = 1;
	p = Head->next;

	while(p!=Head && p->data != x)  /*while( p!= Head && p->data != x) */
	{
		i++;
		p = p->next;
	}

	if(p==Head)  /* if(p->next == Head) */
	{
		return 0;
	}
	else
	{
		return i;
	}

}

输出链表长度

int length(SingleLinkList *Head)
{
	int len=0;
	SingleLinkNode *p;

	p = Head->next;
	while(p!=Head)	/* while(p!=Head) */
	{
		len++;
		p = p->next;
	}
	return len;
}

 输出链表

void print(SingleLinkList *Head)
{
	SingleLinkNode *p;
	int i=0;

	p = Head->next;
	if(p==Head)				/*  if(p!=Head)  */
	{
		printf("链表为空!\n");
		return;
	}
	while(p!=Head)  /* while(p!=Head)  */
	{
		printf("Node[%d]. = %d\n", ++i, p->data);
		p = p->next;
	}
}

运行结果截图 

完整Demo

main.c

#include <stdio.h>
#include <string.h>
#include "SingleLinkList.c"
#include "welcome.h"

int main(int argc, char *argv[])
{
	SingleLinkList *Head;
	DataType x;
	int i, m, n, cmd;

	for (i = 0; i < strlen(welcome); i++)
	{
		printf("%c", welcome[i]);
		for (m = 0; m < 2000; m++)
			for (n = 0; n < 2000; n++)
			{
				;
			}
	}

	printf("-----------简单链表演示程序----------\n");
	do
	{
		printf("1. 初始化链表表\n");
		printf("2. 插入元素(头插法)\n");
		printf("3. 插入元素(尾插法)\n");
		printf("4. 插入元素(在位置i插入)\n");
		printf("5. 查找元素x\n");
		printf("6. 求链表长度\n");
		printf("7. 输出链表\n");
		printf("8. 删除元素\n");
		printf("10. 帮助\n");
		printf("0. 退出\n");
		printf("请输入您要进行的操作(1~6,0退出):");
		scanf("%d", &cmd);
		switch (cmd)
		{
		case 1:
			if (!init(&Head))
			{
				printf("链表已初始化!\n");
			}
			break;
		case 2:
			printf("请输入插入元素x:x=");
			scanf("%d", &x);
			if (!insert_head(&Head, x))
			{
				printf("元素(%d)已插入\n", x);
			}
			break;
		case 3:
			printf("请输入插入元素x:x=");
			scanf("%d", &x);
			if (!insert_tail(&Head, x))
			{
				printf("元素(%d)已插入\n", x);
			}
			break;
		case 4:
			printf("请输入插入元素位置i:");
			scanf("%d", &i);
			printf("请输入插入元素x:");
			scanf("%d",&x);
			if (!insert(&Head, i, x))
			{
				printf("已在位置(%d)插入元素(%d)!\n", i, x);
			}
			break;
		case 5:
			printf("请输入要查找的元素x:");
			scanf("%d", &x);
			if (i = find(Head, x))
			{
				printf("元素%d存在,在链表位置%d.\n", x, i);
			}
			else
			{
				printf("在链表中未找到元素x。\n");
			}
			break;
		case 6:
			printf("链表的长度为:%d\n", length(Head));
			break;
		case 7:
			print(Head);
			break;
		case 8:
			printf("请输入要删除的元素x:");
			scanf("%d", &x);
			if (!delete (&Head, x))
			{
				printf("元素x【%d】已删除!\n", x);
			}
			break;
		case 10:
			printf(" 本程序为链表的演示程序,由陈勇豪设计开发,程序完成了环形链表功能!\n");
			break;
		}
	} while (cmd != 0);

	return 0;
}

SingleLinkList.c

/*
	SingleLinkList.c
	
*/
#include "SingleLinkList.h"
#include <stdlib.h>
#include <stdio.h>

/*1. 初始化*/
int init(SingleLinkList **Head)
{
	if(1)
	{
		/*申请内存*/
		(*Head) = (SingleLinkList*)malloc(sizeof(SingleLinkList));
		/*判断内存申请是否成功*/
		if(*Head == NULL)
		{
			printf("申请内存错误, 初始化失败![100001]\n");
			return 100001;
		}
		(*Head)->next = *Head;
		/*循环链表*/
		/*
			(*Head)->next = *Head;
		*/
		return 0;
	}
	else
	{
		printf("该链表已经初始化!请删除后再执行此操作![100002]\n");
		return 100002;
	}
}


/*2. 插入元素,头插法*/
int insert_head(SingleLinkList **Head, DataType x)
{
	SingleLinkNode *newNode;

	if(0)
	{
		printf("链表未初始化![100003]\n");
		return 100003;
	}
	
	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	if(!newNode)
	{
		printf("申请节点内存空间失败![100004]\n");
		return 100004;
	}
	newNode->data = x;
	newNode->next = (*Head)->next;

	(*Head)->next = newNode;

	return 0;
}


/*2. 插入元素, 尾插法*/
int insert_tail(SingleLinkList **Head, DataType x)
{
	SingleLinkNode *newNode;
	SingleLinkNode *p;

	if(0)
	{
		printf("链表未初始化![100003]\n");
		return 100003;
	}
	
	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	if(!newNode)
	{
		printf("申请节点内存空间失败![100004]\n");
		return 100004;
	}

	newNode->data = x;
	newNode->next = *Head;
	/*
	  循环链表
	  newNode->next = *Head;
	*/

	p = (*Head);

	while(p->next!=*Head)
	{
		p = p->next;
	}

	p->next = newNode;

	return 0;
}


/*2. 插入元素,在位置i处插入元素x */
int insert(SingleLinkList **Head, int i, DataType x)
{
	int j;
	SingleLinkNode *p;
	SingleLinkNode *newNode;

	
	/*对i进行判断,0<i<=length+1*/
	if(i<1 || i>length(*Head)+1)
	{
		printf("位置i不是链表有效位置![100005]\n");
		return 100005;
	}
	p = (*Head);
	j = 1;

	while(j<i)
	{
		j++;
		p = p->next;
	}

	newNode = (SingleLinkNode*)malloc(sizeof(SingleLinkNode));
	/*此处省略检测newNode是否申请成功*/

	newNode->data = x;
	newNode->next = p->next;
	p->next = newNode;
	return 0;
}


/*3. 删除元素, 删除值为x的元素*/
int delete(SingleLinkList **Head, DataType x)
{
	int i;
	int j;

	SingleLinkNode *p;
	SingleLinkNode *q; /*要删除的元素x*/

	i = find(*Head,x);
	if(!i)
	{
		printf("元素x【%d】不存在!100006\n", x);
		return 100006;
	}
	
	p = (*Head);
	j=1;

	while(j<i)
	{
		j++;
		p = p->next;
	}
	
	q = p->next;
	p->next = q->next;

	free(q); /*释放内存*/

	return 0;
}


/*5. 查找值为x的元素,返回位置i */
int find(SingleLinkList *Head, DataType x)
{
	int i;
	SingleLinkNode *p;

	i = 1;
	p = Head->next;

	while(p!=Head && p->data != x)  /*while( p!= Head && p->data != x) */
	{
		i++;
		p = p->next;
	}

	if(p==Head)  /* if(p->next == Head) */
	{
		return 0;
	}
	else
	{
		return i;
	}

}

/*4. 链表长度*/
int length(SingleLinkList *Head)
{
	int len=0;
	SingleLinkNode *p;

	p = Head->next;
	while(p!=Head)	/* while(p!=Head) */
	{
		len++;
		p = p->next;
	}
	return len;
}

/*6.输出链表*/
void print(SingleLinkList *Head)
{
	SingleLinkNode *p;
	int i=0;

	p = Head->next;
	if(p==Head)				/*  if(p!=Head)  */
	{
		printf("链表为空!\n");
		return;
	}
	while(p!=Head)  /* while(p!=Head)  */
	{
		printf("Node[%d]. = %d\n", ++i, p->data);
		p = p->next;
	}
}

SingleLinkList.h

/*SingleLinkList.h*/

typedef int DataType;

/*简单链表的定义*/
typedef struct node
{
	DataType		data;	/*数据域*/
	struct node		*next;	/*指针域*/
}SingleLinkList, SingleLinkNode;


/*1. 初始化*/
int init(SingleLinkList **Head);

/*2. 插入元素,头插法*/
int insert_head(SingleLinkList **Head, DataType x);

/*2. 插入元素, 尾插法*/
int insert_tail(SingleLinkList **Head, DataType x);

/*2. 插入元素,在位置i处插入元素x */
int insert(SingleLinkList **Head, int i, DataType x);

/*3. 删除元素, 删除值为x的元素*/
int delete(SingleLinkList **Head, DataType x);

/*5. 查找值为x的元素,返回位置i */
int find(SingleLinkList *Head, DataType x);

/*6. 求链表的长度 */
int length(SingleLinkList *Head);

/*7.输出链表*/
void print(SingleLinkList *Head);

welcome.h 

char welcome[] = "\n\
                               \n\                      
                                  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n\                              
                                  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n\                              
                                  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n\                              
                                  IIIII    IIIIIIIIIII     IIIIIII\n\                              
                                  IIIIIII     IIIIIIIIII   IIIIIII\n\                              
                                  IIIIIIIII     IIIIIIIIIIIIIIIIII\n\                              
                                  IIIIIIIIIII       IIIIIIIIIIIIII\n\                              
                                  IIIIIIIIIIIII        IIIIIIIIIII\n\                              
                                  IIIIIIIIIIIIIII         IIIIIIII\n\                              
                                  IIIIIIIIIIIIIIIII         IIIIII\n\                              
                                  IIIII    IIIIIIIIIII        IIII\n\                              
                                  IIIII     IIIIIIIIIII      IIIII\n\                              
                                  IIIII      IIIIIIIIIII    IIIIII\n\                              
                                  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n\                              
                                  IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\n\n\n\                                                                                                               
      IIIIIIIII.           .IIIIIIIII.       IIIIIIIIIIIII          I            .IIIIIII.\n\      
      III      III        III       III      I.   III   .I         III          III    III\n\      
      III       III      III         III          III             II II               III\n\       
      III        III     III          II          III            II  III             III\n\        
      III        III     III          II          III           II    III           III\n\         
      III       III       III        II           III          II      III         III\n\          
      III      II          IIII     II            III          IIIIIIIIIII        III    .I\n\     
      IIIIIIIIII             IIIIIII              III          II       II       IIIIIIIIII\n\n";

小结 

链表是一种基本的数据结构,它由节点组成,每个节点通常包含数据(例如整数或其他类型)和指向下一个节点的指针。每个节点包含数据和指向下一个节点的引用。链表的核心操作包括在特定位置插入或删除节点。这需要小心调整节点的指针。循环链表的最后一个节点指向第一个节点,使得链表可以无限循环遍历,适用于需要连续循环操作的情况。总之,链表是一种灵活的数据结构,适用于各种动态数据管理需求,但需要小心处理节点指针以维护链表的完整性。

参考文献:《数据结构(C语言版)》李刚、刘万辉主编,高等教育出版社。OpenAI

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值