用C语言写循环链表

95 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

1、循环链表图解

感觉所有链表都基于单链表,单链表的最后一个节点的指针域指向NULL,如果把它指向第一个节点,就像形成了循环链表。如果是无头单链表表,结果就是图一那样无头的循环链表,如果是有头节点,结果就是图二那样的有头的循环链表。

无头结点 image.png

有头节点 image.png

2、定义循环链表的结构体

定义方式和但链表一样

typedef int DataType;
typedef struct circulate
{
	DataType data;
	struct circulate *next;
}Circulate, *CirculateList;

3、使用函数创建循环链表

CirculateList Creat(int n)//无头
{
	int i = 1;
	CirculateList L, p, r;
	L = (CirculateList)malloc(sizeof(Circulate));
	L->next = NULL;
	p = L;
	scanf("%d", &p->data);
        //如果不给这个节点赋值,就是有头链表,p->next=L->next时期形成闭环。
	while (i++<n)
	{
		r = (CirculateList)malloc(sizeof(Circulate));
		r->next = NULL;
		scanf("%d", &r->data);
		p->next = r;
		p = r;
	}
	p->next = L;//如果没有这句话就是创建单链表
	return L;
}

4、求表长

(1)DataType *p 获取某个节点的地址 (2)遍历循环链表,i++; (3)如果节点r->data的地址等于p,说明循环链表已经遍历一遍,跳出循环

int Get_Length(CirculateList L)
{
	int length=0;
	CirculateList h = L; 
	DataType *p = &h->data;//后去地址,作为标记
	h = h->next;//从标记点的下一个节点开始计数
	while (p!=&h->data)//直到回到标记点
	{
		length++;//长度加1
		h = h->next;//后移
	}
	return length+1;//标记点出没有加1,所以在return时length+1
}

5、删除节点

删除节点和插入节点都是和单链表一样的

image.png 使用while循环找到要删除的位置之后:

    p=h->next;
    h->next = p->next;

删除h的下一个节点 如果是while(i++<n-1)那么就会找到h的前驱节点,最后删除的就是下标为n的节点了。

CirculateList Circulate_Delete(CirculateList L, int n)
{
	CirculateList h = L,p;
	p = (CirculateList)malloc(sizeof(Circulate));
	p->next = NULL;
	int i = 0;
	while (i++<n-1)//查找
	{
		h = h->next;
	}
	p=h->next;
	h->next = p->next;
	return h;//我写的是返回h而不是L,否则不能删除第一个节点.
}

6、插入节点

删除节点和插入节点都是和单链表一样的

CirculateList CirculateList_Inster(CirculateList L ,int n,CirculateList r)
{
	
	int i = 0;
	CirculateList h=L;
	while (i++ < n)//找位置
	{
		h = h->next;
	}
	r->next = h->next;//先衔接
	h->next = r;//都断开
	return L;
}