博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
链表之循环链表
阅读量:5234 次
发布时间:2019-06-14

本文共 6255 字,大约阅读时间需要 20 分钟。

上期文章介绍了单链表的一些基本功能函数,本次主要介绍循环链表的一些基本功能函数。循环链表其实就是将单链表的最后一个结点指向单链表的头结点,从而构成一个循环结构。本次函数功能主要包括链表创建函数(头插法和尾插法)链表打印函数两种链表是否有环的判定函数,以及最后的一个链表清除函数

  • 博文链接:
  • 对,我是来骗访问量的!O(∩_∩)O~~

函数运行如下图所示:

cLinkList

功能函数

链表创建函数(头插法)

//定义循环链表生成函数(头插法)void cListCreatHead(cLinkList *L, int n){    int i;    cLinkList *p, *r;    p = L;    p->data = rand() % 100 + 1;    for(i = 1; i < n; ++i)    {        r = (cLinkList *)malloc(sizeof(cLinkList));        r->data = rand() % 100 + 1;        r->next = p;        p = r;    }    L->next = p;}

这里使用了头插法对链表进行生成操作,L作为cLinkList的一个指针,指向链表的最后一个结点,这里注意最后要将L指向p构建循环。

链表创建函数(尾插法)

//定义循环链表生成函数(尾插法)void cListCreatTail(cLinkList *L, int n){    int i;    cLinkList *head, *p;    head = L;    L->data = rand() % 100 + 1;    for(i = 1; i < n; i++)    {        p = (cLinkList *)malloc(sizeof(cLinkList));        p->data = rand() % 100 + 1;        L->next = p;        L = p;    }    L->next = head;}

这里使用了尾插法对链表进行生成操作,L作为cLinkList的一个指针,在创建过程中不断向后移动,最后指向链表的最后一个结点,这里注意最后要将L指向头结点指针head构建循环。

链表打印函数

void cListPrint(cLinkList *L){    cLinkList *head, *p;    head = L;    p = L;    int count = 1;    while(p->next != head)    {        printf("%d\t", p->data);        p = p->next;        count++;    }    printf("%d\n", p->data);    printf("The length of this LinkList is: %d\n", count);}

通过判定p->next != head为条件对链表进行遍历打印,在遍历过程中计算链表的长度并打印输出。

检测是否有环(方法一)

//检查是否有环(方法一)int cListCheckLoop1(cLinkList *L){    cLinkList *head, *p, *q;    head = p = q = L;    int countp, countq;    countp = 1;    while(1)    {        p=p->next;        countp++;        countq = 1;        q = head;        while(q != p)        {            q = q->next;            countq++;        }        if(++countq != countp)        {            printf("YES!\nThere is a loop in the LinkList!\n");            return 1;        }        if(p->next == NULL)        {            printf("NO!\nThere is no loop in the LinkLis!\n");            return 0;        }    }}

设置指针变量p对链表进行遍历,同时使用qp之前的结点进行遍历,如果发现到达p所在结点的更短路径,则判定链表存在环。比如,p走了6步到达结点A,而q只需要3步即可到达结点A,则此时链表中必定存在环,换言之,此前p已经经过结点A了。

检测是否有环(方法二)

//检测链表是否有环(方法二)int cListCheckLoop2(cLinkList *L){    cLinkList *p, *q;    p = q = L;    while(p->next != NULL && p->next->next != NULL)    {        p = p->next->next;        q = q->next;        if(p == q)        {            printf("YES!\nThere is a loop in this LinkList\n");            return 1;        }    }    printf("NO!\nThere is no loop in the LinkList\n");    return 0;}

设置p的步长为2,q的步长为1,同时对链表进行遍历,如果在某个时刻p == q,则就可以断定链表中存在环。

链表清除

//链表清除函数void cListClear(cLinkList *L){    cLinkList *p, *temp;    p = L->next;    while(p != L)    {       temp = p;       p = p->next;       free(temp);    }}

使用free()函数对我们生成的链表空间进行遍历删除。


总体代码

#include 
#include
//定义循环链表结构typedef struct node{ int data; struct node *next;}cLinkList;//定义循环链表生成函数(头插法)void cListCreatHead(cLinkList *L, int n){ int i; cLinkList *p, *r; p = L; p->data = rand() % 100 + 1; for(i = 1; i < n; ++i) { r = (cLinkList *)malloc(sizeof(cLinkList)); r->data = rand() % 100 + 1; r->next = p; p = r; } L->next = p;}//定义循环链表生成函数(尾插法)void cListCreatTail(cLinkList *L, int n){ int i; cLinkList *head, *p; head = L; L->data = rand() % 100 + 1; for(i = 1; i < n; i++) { p = (cLinkList *)malloc(sizeof(cLinkList)); p->data = rand() % 100 + 1; L->next = p; L = p; } L->next = head;}//打印链表void cListPrint(cLinkList *L){ cLinkList *head, *p; head = L; p = L; int count = 1; while(p->next != head) { printf("%d\t", p->data); p = p->next; count++; } printf("%d\n", p->data); printf("The length of this LinkList is: %d\n", count);}//检查是否有环(方法一)int cListCheckLoop1(cLinkList *L){ cLinkList *head, *p, *q; head = p = q = L; int countp, countq; countp = 1; while(1) { p=p->next; countp++; countq = 1; q = head; while(q != p) { q = q->next; countq++; } if(++countq != countp) { printf("YES!\nThere is a loop in the LinkList!\n"); return 1; } if(p->next == NULL) { printf("NO!\nThere is no loop in the LinkLis!\n"); return 0; } }}//检测链表是否有环(方法二)int cListCheckLoop2(cLinkList *L){ cLinkList *p, *q; p = q = L; while(p->next != NULL && p->next->next != NULL) { p = p->next->next; q = q->next; if(p == q) { printf("YES!\nThere is a loop in this LinkList\n"); return 1; } } printf("NO!\nThere is no loop in the LinkList\n"); return 0;}//清除链表void cListClear(cLinkList *L){ cLinkList *p, *temp; p = L->next; while(p != L) { temp = p; p = p->next; free(temp); }}//主函数int main(){ int length = 10; cLinkList *L; L = (cLinkList *)malloc(sizeof(cLinkList)); char operator; printf("1.生成链表(头插法)\n"); printf("2.生成链表(尾插法)\n"); printf("3.打印链表\n"); printf("4.判断链表是否有环(方法一)\n"); printf("5.判断链表是否有环(方法二)\n"); printf("6.清除链表\n"); printf("0.退出\n"); while(1) { scanf("%c", &operator); switch(operator) { case '1': cListCreatHead(L, length); printf("**********生成链表(头)!**********\n"); break; case '2': cListCreatTail(L, length); printf("**********生成链表(尾)!**********\n"); break; case '3': printf("*************打印链表!*************\n"); cListPrint(L); break; case '4': printf("***********是否有环(一)***********\n"); cListCheckLoop1(L); break; case '5': printf("***********是否有环(二)***********\n"); cListCheckLoop2(L); break; case '6': printf("*************清除链表!*************\n"); cListClear(L); break; case '0': printf("***************退出*****************\n"); free(L); return 0; } } return 0;}

github

个人博客

个人站点,欢迎访问,欢迎评论!

转载于:https://www.cnblogs.com/zuilehongdou/p/5527818.html

你可能感兴趣的文章
关于MySQL去除查询结果重复值
查看>>
当后台给的数据格式没有规律的时候,前端自我处理方式
查看>>
[转]SpringMVC拦截器详解[附带源码分析]
查看>>
题解 CF1119A 【Ilya and a Colorful Walk】
查看>>
如何做好产品
查看>>
JS windows对象的top属性
查看>>
单点登录三个方法及原理:共享Session、基于OpenId的单点登录、基于Cookie的OpenId存储方案...
查看>>
BNUOJ-26482 Juice 树形DP
查看>>
HDU-4722 Good Numbers 数位DP
查看>>
ios: 仿照【ONE】应用中的阅读滑动效果
查看>>
【leetcode】Binary Tree Maximum Path Sum
查看>>
安装AAA服务器遇到的问题
查看>>
ObjectARX: 得到全部已打开文档
查看>>
[javascript]快速交换javascript变量的值
查看>>
ASP.NET MVC4 IN ACTION学习笔记-第六波[Ajax in ASP.NET MVC][3/3]
查看>>
Windows7如何清理/禁用搜索历史记录
查看>>
MySQL多实例配置
查看>>
CodeForces - 877B Nikita and string
查看>>
nyoj 21三个水杯(搜索)
查看>>
vb.net 浏览文件夹读取指定文件夹下的csv文件 并验证,显示错误信息
查看>>