- 单链表练习题-构造环以及判断是否有环(C语言实现)
- 一.题目
- 二.构造环
- 三.判断是否有环
- 四.全部代码
- 五.测试
如下图所示:
本次就是要构造环以及判断是否有环。
二.构造环 构造环比较简单,只需要修改某个结点的指针就可以了,为了方便我这里直接修改尾结点的指针,使其指向指定元素的后继,这样就构成了一个环。
bool Make_Loop(linkList *L,ElemType e) //构造环,直接让尾指针指向特定结点的后继
{
linkList *q,*s,*tail;//*s标记特定的结点,tail表示最后一个结点
q = L->next;
//打印出所有元素
while(q->next!=NULL)
{
if(q->data==e)//找到指定结点
s = q;
q = q->next;
}
tail = q;//跳出while循环时,q已经指向了最后一个结点
//构造环
tail->next = s->next;
return true;
}
三.判断是否有环
判断是否有环也比较简单,思路是:设置一个快指针和慢指针,慢指针每次走一步,快指针每次走两步,如果环存在,那么快指针总能追上慢指针,也就是如果快慢指针能指向同一个元素的时候,那么说明是有环的。反之,如果快慢指针无法相遇,那么链表就无环。
bool Is_Loop(linkList *L)//判断链表是否有环,有环现在能判断
{
linkList *slow,*fast;
slow = fast = L->next;
fast = fast->next;//fast先走一步
while((slow!=NULL)&&(fast->next!=NULL))
{
slow = slow->next;//slow指针每次走一步
fast = fast->next;//fast指针每次走两步
fast = fast->next;
if(slow == fast)//如果快慢指针相遇,说明环存在,直接返回true
return true;
}
return false;//如果指针到了末尾函数还没返回,说明环不存在
}
四.全部代码
#include五.测试#include #include //根据C99标准,C语言使用bool类型需要添加这个头文件 typedef int ElemType; typedef struct linkNode { ElemType data; struct linkNode *next; }linkList; //------------ 函数声明 ----------// void MainMenu(); bool InitlinkList(linkList *L);//初始化 bool InsertlinkList(linkList *L,ElemType e);//插入 void PrintAll(linkList *L);//输出所有元素 bool Make_Loop(linkList *L,ElemType e); //构造环 bool Is_Loop(linkList *L);//判断链表是否有环 //------------ 函数声明 ----------// int main() { linkList L; int ch; ElemType element; if(InitlinkList(&L)) printf("初始化成功!n"); else printf("初始化失败!n"); while(1) { MainMenu(); printf("请输入您要执行的操作:"); scanf("%d",&ch); switch(ch) { case 0: printf("感谢使用,已退出!"); exit(0); break; case 1: printf("请输入您要插入的元素:n"); scanf("%d",&element); if(InsertlinkList(&L,element)) printf("插入成功!n"); else printf("插入失败!n"); break; case 2: PrintAll(&L); break; case 3: printf("请输入您要让环指针指向的元素:n"); scanf("%d",&element); if(Make_Loop(&L,element)) printf("环构造成功!n"); else printf("环构造失败!n"); break; case 4: if(Is_Loop(&L)) printf("链表有环!n"); else printf("链表无环!n"); break; default: printf("您输入的操作指令有误!请重新输入!"); } } return 0; } //主菜单,显示 void MainMenu() { printf("nnn"); printf("t **** 单链表构造环、判断是否有环 ****nn"); printf("t ------- 0.退出 nn"); printf("t ------- 1.插入元素nn"); printf("t ------- 2.输出所有元素nn"); printf("t ------- 3.使链表构成环nn"); printf("t ------- 4.判断链表是否有环nn"); printf("t *************************************n"); } //初始化单链表(带头结点) bool InitlinkList(linkList *L) { //先申请一个头结点 linkList *head = (linkList *)malloc(sizeof(linkList)); L->next = head; head->next = NULL;//头结点之后一开始还没元素 return true; } //插入 bool InsertlinkList(linkList *L,ElemType e) { //头插法 linkList *p = L;// //申请一个新的结点 linkList *s = (linkList *)malloc(sizeof(linkList)); s->data = e;//赋值 //修改指针 将结点s插入到结点p之后 s->next = p->next;//s指针指向 p->next = s; return true; } //打印所有元素 void PrintAll(linkList *L) { linkList *q; q = L->next; //打印出所有元素 while(q->next!=NULL) { printf("%d ",q->data); q = q->next; } } bool Make_Loop(linkList *L,ElemType e) //构造环,直接让尾指针指向特定结点的后继 { linkList *q,*s,*tail;//*s标记特定的结点,tail表示最后一个结点 q = L->next; //打印出所有元素 while(q->next!=NULL) { if(q->data==e)//找到指定结点 s = q; q = q->next; } tail = q;//跳出while循环时,q已经指向了最后一个结点 //构造环 tail->next = s->next; return true; } bool Is_Loop(linkList *L)//判断链表是否有环,有环现在能判断 { linkList *slow,*fast; slow = fast = L->next; fast = fast->next;//fast先走一步 while((slow!=NULL)&&(fast->next!=NULL)) { slow = slow->next;//slow指针每次走一步 fast = fast->next;//fast指针每次走两步 fast = fast->next; if(slow == fast) return true; } return false; }
1.首先依次插入元素并输出:
2.此时是无环的,先判断一下算法是否正确:
3.判断正确,那就构造一个环:
4.再来判断是否有环:
完成。



