找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1728|回复: 0
收起左侧

C++语言判断单链表是否有环链表 程序源码

[复制链接]
ID:618366 发表于 2021-9-12 11:25 | 显示全部楼层 |阅读模式
1.问题:如果给定一个单链表,如何判断其是否为有环链表
2.方法:
(1)从给定链表的第一个节点开始遍历,每遍历至一个节点,都将其和所有的前驱节点进行比对,如果为同一个节点,则表明当前链表中有环;反之,如果遍历至链表最后一个节点,仍未找到相同的节点,则证明该链表中无环。
NBQ(S_`2~N$F_E2A_CB`P[2.png

如上所示,当函数的返回值为 True,表示该链表有环;反之若函数返回值为 False,表明链表中无环。显然,此实现方案的时间复杂度为O(n2)。
(2)在一个链表中,如果 2 个指针(假设为 H1 和 H2)都从表头开始遍历链表,其中 H1 每次移动 2 个节点的长度(H1 = H1->next->next),而 H2 每次移动 1 个节点的长度(H2 = H2->next),如果该链表为有环链表,则 H1、H2 最终必定会相等;反之,如果该链表中无环,则 H1、H2 永远不会相遇。
2.png

本算法的时间复杂度为 O(n)。

  1. #include<stdio.h>
  2. #include<stdlib.h>

  3. //自定义 bool 类型
  4. typedef enum Bool
  5. {
  6.     False=0,
  7.     True=1
  8. }Bool;

  9. typedef struct link{
  10.     int data;
  11.     struct link* next;
  12. }link;

  13. link *linkIint(int n)
  14. {
  15.     link *head=(link*)malloc(sizeof(link));
  16.     head->data=1;
  17.     head->next=NULL;
  18.     link *phead=head;
  19.     int i;
  20.     for(i=2;i<=n;i++)
  21.     {
  22.         link *temp=(link*)malloc(sizeof(link));
  23.         temp->data=i;
  24.         temp->next=NULL;

  25.         head->next=temp;
  26.         head=head->next;
  27.     }
  28.         head->next=phead;
  29.     return phead;
  30. }

  31. #if 1
  32. Bool HaveRing(link *temp)
  33. {
  34.     link *H2=temp;
  35.     link *H1=temp->next;
  36.         if(H2==NULL||H2==NULL)
  37.         {
  38.                 return False;
  39.         }
  40.     while(H1)
  41.     {
  42.         if(H1==H2)
  43.         {
  44.             printf("this links have a ring\n");
  45.             return True;
  46.         }
  47.         else
  48.         {
  49.             H1=H1->next;
  50.             if (!H1)
  51.             {
  52.                 printf("this links no ring\n");
  53.                 return False;
  54.             }
  55.             else
  56.             {
  57.                 H1=H1->next;
  58.                 H2=H2->next;
  59.             }
  60.         }
  61.     }
  62.     //链表中无环
  63.     printf("this links no ring\n");
  64.     return False;
  65. }
  66. #else

  67. Bool HaveRing(link *H)
  68. {
  69.     link * Htemp = H;
  70.     //存储所遍历节点所有前驱节点的存储地址,64位环境下地址占 8 个字节,所以这里用 long long 类型
  71.     long long addr[20] = { 0 };
  72.     int length = 0, i = 0;
  73.         if(Htemp==NULL||Htemp->next==NULL)
  74.         {
  75.                 return False;
  76.         }
  77.     //逐个遍历链表中各个节点
  78.     while (Htemp) {
  79.         //依次将 Htemp 和 addr 数组中记录的已遍历的地址进行比对
  80.         for (i = 0; i < length; i++) {
  81.             //如果比对成功,则证明有环
  82.             if (Htemp == (link*)addr[i]) {
  83.                 return True;
  84.             }
  85.         }
  86.         //比对不成功,则记录 Htemp 节点的存储地址
  87.         addr[length] = (long long)Htemp;
  88.         length++;
  89.         Htemp = Htemp->next;
  90.     }
  91.     return False;
  92. }

  93. #endif

  94. void linkPrint(link *temp)
  95. {
  96.         link *phead=temp;
  97.     if(!temp)
  98.         printf("the link is empty\n");
  99.     else
  100.     {
  101.         while(temp)
  102.         {
  103.             printf("%d\t",temp->data);
  104.             temp=temp->next;
  105.             if(temp==phead)
  106.             {
  107.                                 printf("\r\n");
  108.                 break;
  109.             }
  110.         }
  111.     }
  112. }

  113. int main()
  114. {
  115.     link *head=linkIint(6);
  116.     linkPrint(head);
  117.     if(HaveRing(head)==True)
  118.         {
  119.                 printf("the link has a ring\r\n");
  120.         }
  121.         else
  122.         {
  123.                 printf("the link no rave\r\n");
  124.         }
  125.     return 0;
  126. }
复制代码


51hei.png

3.以上源码: 有环链表判定.7z (1.09 KB, 下载次数: 5)

评分

参与人数 1黑币 +30 收起 理由
admin + 30 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表