持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
1、循环链表图解
感觉所有链表都基于单链表,单链表的最后一个节点的指针域指向NULL,如果把它指向第一个节点,就像形成了循环链表。如果是无头单链表表,结果就是图一那样无头的循环链表,如果是有头节点,结果就是图二那样的有头的循环链表。
无头结点
有头节点
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、删除节点
删除节点和插入节点都是和单链表一样的
使用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;
}