所谓循环链表就是最后一个节点的指针域不是指向空,而是指向第一个节点,这样就实现了循环。
下面是c语言代码实现
LinkList create_linklist()
{
int len; //用来存储节点的个数
int i; //for循环中的循环变量
int val; //用来存放节点的值域
LinkList Ll = NULL; //Ll用来存储指向第一个节点的指针
LinkList pre = NULL; //pre用来存储指向LNew指向节点的前驱节点的指针,初始指向第一个节点
//请求用户输入节点个数
printf("请输入节点的个数:\n");
scanf("%d", &len);
for (i = 0; i < len; i++)
{
//每循环一次生成一个新的节点
LinkList LNew = (LinkList)malloc(sizeof(LNode));
//判断是否分配成功
if(!LNew)
{
printf("动态内存分配失败,程序退出!\n");
exit(-1);
}
//请求用户输入新节点的值
printf("请输入第%d个节点的值\n", i+1);
scanf("%d", &val);
//i = 0时,即循环第一次运行时(生成第一个节点时)
if(0 == i)
{
//将指向第一个节点的指针保存在Ll中,便于后续操作
Ll = LNew;
//初始化pre,使其指向第一个节点
pre = Ll;
}
//将用户输入的值存储到数据域
LNew->data = val;
//将原来的节点挂在新生成的节点上
pre->pNext = LNew;
//新节点变成当前的最后一个节点,需要将其指针域指向第一个节点,从而形成循环单链表
LNew->pNext = Ll;
//pre后移,使其始终指向LNew指向节点的前驱节点,便于进行将LNew指向节点的前驱节点(原来的节点)挂在LNew指向的节点(新生成的节点)上的操作
pre = LNew;
}
//提示用户链表创建成功
printf("链表创建成功!\n");
//返回指向第一个节点的指针
return Ll;
}
接下来是求链表长度的操作
int length_list(LinkList Ll)
{
int len = 1; //用来存储链表长度,初始值为1
LinkList p = Ll;
//如果指向第一个节点的指针为空,链表长度为0
if(!Ll)
return 0;
//如果p->pNext不指向第一个节点,表示p不是最后一个节点,则p后移一位,直到p->pNext指向第一个节点为止
while(p->pNext != Ll)
{
//长度加一
len++;
//p后移一位
p = p->pNext;
}
//返回链表长度
return len;
}
下面是遍历输出的操作
//不含头结点的循环单链表的遍历输出
void show_linklist(LinkList Ll)
{
LinkList p = Ll;
if(!Ll)
return;
while(true)
{
printf("%d ", p->data);
p = p->pNext;
if(p == Ll)
break;
}
printf("\n");
return;
}
最后是删除操作(其中删除第一个节点比较特别)
void delete_node(LinkList * Ll, int pos) //Ll是指向第一个节点的指针的指针,pos是要删除节点的位置,最小值为1,最大值为链表长度
{
int i; //for中的循环变量
LinkList p = * Ll; //定义一个始终指向要删除节点的前驱节点的指针,初始指向第一个节点
//判断链表是否为空
if(!length_list(* Ll))
{
//提示用户链表为空
printf("链表为空,无法删除!\n");
//结束函数
return;
}
//判断pos是否可执行
if(pos < 1 || pos > length_list(* Ll))
{
//提示用户pos输入有误
printf("删除位置过小或过大,无法删除\n");
//结束函数
return;
}
//如果删除的是第一个节点
if(1 == pos)
{
//先通过for循环找到指向最后一个节点的指针(因为是循环链表,这里的最后一个节点,相当于第一个节点的前驱节点)
for (i = 0; i < length_list(* Ll) - 1; i++)
{
p = p->pNext;
}
// 第一个节点的前驱节点挂在第一个节点的后驱节点上
p->pNext = (* Ll)->pNext;
//释放为一个节点分配的空间
free(* Ll);
//原来的第二个节点成为新的第一个节点(这一步是传值操作,这样以后才能找到这个链表)
(* Ll) = p->pNext;
//结束函数
return;
}
//如果不是删除第一个节点,就要找到指向要删除节点的前驱节点的指针
for(i = 1; i<pos-1; i++)
{
p = p->pNext;//p后移一位
}
//定义一个指向要删除节点的指针
LinkList q = p->pNext;
//将要删除节点的前驱节点挂在,要删除节点的后驱节点上
p->pNext = q->pNext;
//释放为要删除节点分配的空间
free(q);
q = NULL;
//提示用户删除成功
printf("删除成功!\n");
//结束函数
return;
}