判断一个单链表是否有环及环的链接点(转)

FreeCAD源码分析:Sketcher模块 Sketcher模块基于Part模块功能实现了特征编辑(Feature Editing)建模的功能。这类参数化建模系统主要包括几何表示、约束求解器等两大组成部分。 阅读详情

给定一个单链表,只给出头指针h:

1、如何判断是否存在环?

2、如何知道环的长度?

3、如何找出环的连接点在哪里?

4、带环链表的长度是多少?

 

解法:

1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。

2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点开始,再次碰撞所走过的操作数就是环的长度s。

3、问题3:有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。(证明在后面附注)

4、问题3中已经求出连接点距离头指针的长度,加上问题2中求出的环的长度,二者之和就是带环单链表的长度

void Isloop(Llink head)
{
 if(!head||!head->next)
  return;
 Llink p,q;
 bool loop=false;
 p=q=head->next;
 while(q&&q->next)//判断是否有环
 {
  p=p->next;
  q=q->next->next;
  if(p==q)
  {
   loop=true;
   break;
  }
 }
 if(!loop)
  cout<<"This link has not loop\n";
 else
 {
  cout<<"This link has a loop\n";
  Llink r=p;
  q=head->next;
  int nonloop=1,loopcount=1;

  //nonloop计算非环结点数,loopcount计算环上结点数
  do//计算环上的结点数
  {
   p=p->next;
   ++loopcount;
  }while(p!=r);
  --loopcount;
  while(p!=q)//得到环的入口结点,同时计算得到非环的结点数
  {
   p=p->next;
   q=q->next;
   ++nonloop;
  }
  --nonloop;
  cout<<"\nStart of loop: "<<p->data<<endl;  
  cout<<"\nCount of nonloop: "<<nonloop
      <<"\nCount of loop: "<<loopcount
      <<"\nCount of Linknode: "<<nonloop+loopcount<<endl;
 }
}

  

判断是否存在环的程序:

bool IsExitsLoop(slist *head)  
  1. {  
  2.     slist *slow = head, *fast = head;  
  3.     while ( fast && fast->next )   
  4.     {  
  5.         slow = slow->next;  
  6.         fast = fast->next->next;  
  7.         if ( slow == fast ) break;  
  8.     }    
  9.     return !(fast == NULL || fast->next == NULL);  
  10. }  

 

寻找环连接点(入口点)的程序:

slist* FindLoopPort(slist *head)  
  1. {  
  2.     slist *slow = head, *fast = head;    
  3.     while ( fast && fast->next )   
  4.     {  
  5.         slow = slow->next;  
  6.         fast = fast->next->next;  
  7.         if ( slow == fast ) break;  
  8.     }    
  9.     if (fast == NULL || fast->next == NULL)  
  10.         return NULL;  
  11.     slow = head;  
  12.     while (slow != fast)  
  13.     {  
  14.          slow = slow->next;  
  15.          fast = fast->next;  
  16.     }  
  17.     return slow;  
  18. } 

亦可以用类似与hash表的方法,即设立一个数组,将链表结点中的值做数组下标,当赋值冲突时就是环的接入点

  1.  bool isloop(Llink p)
    {
     if(!p||!p->next)
      return true;
     int a[MAXSIZE],n=0;
     memset(a,0,sizeof(int)*MAXSIZE);
     p=p->next;
     while(p)
     {
      if(a[p->data]==-1)//存在环时,会发生冲突
      {
       cout<<"\nLoop node: "<<p->data<<endl
        <<"\nLen of node: "<<n<<endl;
       return true;
      }
      a[p->data]=-1;
      ++n;
      p=p->next;
     }
     return false;
    }
    Llink CreatlinkLoop()
  2. //创建一个有环的链表
    {
     Llink head=new Lnode;
     //head->data=0;
     head->next=NULL;
     Lelemtype e;
     Llink q=head;
     int N=0;
     cout<<"input elems:";
     while(cin>>e)
     {
      Llink p=new Lnode;
      ++N;
      p->data=e;
      p->next=q->next;
      q->next=p;
      q=p;
     }
     cin.clear();
     cin.sync();
     srand(time(0));
     q->next=Findnode(head,rand()%N);//随机产生环的接入点
     return head;
    }
    Llink Findnode(Llink head,int n)//找出链表中的第n个结点
    {
     if(n<=0)
      return head;
     Llink p=head->next;
     for(int i=1;p&&i<n;++i)
      p=p->next;
     return p;
    }

////////////////////////////////////////////////////////

附注

问题2的证明如下:

链表形状类似数字 6 。
假设甩尾(在环外)长度为 a(结点个数),环内长度为 b 。
则总长度(也是总结点数)为 a+b 。
从头开始,0 base 编号。
将第 i 步访问的结点用 S(i) 表示。i = 0, 1 ...
当 i<a 时,S(i)=i ;
当 i≥a 时,S(i)=a+(i-a)%b 。

分析追赶过程:
两个指针分别前进,假定经过 x 步后,碰撞。则有:S(x)=S(2x)
由环的周期性有:2x=tb+x 。得到 x=tb 。
另,碰撞时,必须在环内,不可能在甩尾段,有 x>=a 。

连接点为从起点走 a 步,即 S(a)。
S(a) = S(tb+a) = S(x+a)。
得到结论:从碰撞点 x 前进 a 步即为连接点。

根据假设易知 S(a-1) 在甩尾段,S(a) 在环上,而 S(x+a) 必然在环上。所以可以发生碰撞。
而,同为前进 a 步,同为连接点,所以必然发生碰撞。

综上,从 x 点和从起点同步前进,第一个碰撞点就是连接点。

/////////////////////////////////////////////////////////////

假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为r,慢指针总共走了s步,则快指针走了2s步。另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x的距离),得到以下关系:
    s = a + x;
    2s = a + nr + x;
    =>a + x = nr;
    =>a = nr - x;
    由上式可知:若在头结点和相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点,搞掂!
附图:

带环的链表
告别连接难题:Windows 11下Multisim主数据库稳定运行终极配置指南 本文详细解析了Windows 11下Multisim 14.0主数据库连接失败的三大根源,并提供了四步终极解决方案,包括系统环境优化、软件权限配置、注册表修复和网络验证绕过技巧。通过实测数据对比,本方案显著提升了启动速度和稳定性,解决了电子仿真中的常见连接问题。 阅读详情

相关推荐

LVGL的基础知识总结

另外,还有自定义字库的使用,具体可参考开发手册。

qq_28576837的博客 7387

判断链表中是否有环 ----- 有关单链表中环的问题

给定一个单链表,判断其中是否有环,已经是一个比较老同时也是比较经典的问题,在网上搜集了一些资料, 然后总结一下大概可以涉及到的问题,以及相应的解法。 首先,关于单链表中的环,一般涉及到一下问题: 1.给一个单链表,判断其中是否有环的存在; 2.如果存在环,找出环的入口点; 3.如果存在环,求出环上节点的个数; 4.如果存在环,求出链表的长度; 5.如果存在环,求出环上距离任意...

weixin_30681615的博客 462

带硬约束的物理信息神经网络(PINN with Hard Constraint)示例及代码

本文以一个案例介绍了带硬约束的物理信息神经网络的原理及实现步骤。

m0_72768523的博客 5356

三、线性表——链表

三、链表 1.快慢指针 1)如何判断单链表是否存在环 ? 问题描述:给定一个单链表L,L为头指针,判断该链表内是否局部存在环? 方法: 快慢指针,快指针的速度为慢指针的2倍,若快慢指针相遇则有环。 #include<iostream> using namespace std; typedef struct LNode //定义单链表 { int data; struct LNode *next; }LNode, *LinkList; void List_TailInsert(LinkL

as_your_heart的博客 583

coredump文件的原理是啥

Core Dump(核心转储)是操作系统在程序崩溃(如段错误、非法指令等)时自动生成的一个文件,它包含了程序崩溃瞬间的。通过 core dump,开发者可以像“时间回溯”一样检查程序崩溃瞬间的状态,是调试复杂问题的利器!终止时,Linux 内核会生成 core 文件。不会生成 core dump,因为它们是“优雅终止”信号。这样 core 文件会直接压缩存储,节省磁盘空间。的文件(类似可执行文件),可以用。Core 文件本质上是一个。

二进制君 381

YOLOv11 改进 - 注意力机制 | LS-YOLO MSFE 多尺度特征提取模块:并行分支结构增强多尺度感知,优化遥感与小目标检测

本文介绍了一种用于滑坡检测的模型LS-YOLO及其在YOLOv11中的结合应用。LS-YOLO首先构建多尺度滑坡数据集MSLD,为模型训练提供丰富数据。设计了基于高效通道注意力、平均池化和空间可分离卷积的多尺度特征提取模块MSFE,充分提取滑坡特征信息。在解耦头中采用膨胀卷积增加模型感受野。我们将MSFE模块集成进YOLOv11,替换部分原有模块。实验表明,改进后的YOLOv11在数据集中表现出色 。

魔改工程师的博客 870

判断单链表内是否存在环

首先,有一个简单的代码可以判断: listnode_ptr current =head->next; while(current) {   if(current==head)   {     printf("YES!\n");     return 0;   }   else   {     cu

zp208151138的博客 329

GEE案例教程:融合Sentinel-1 SAR数据、Sentinel-2光学影像和WorldPop人口数据,构建完整的洪水监测与影响评估工作流

本文介绍了一个专为巴基斯坦哈扎拉分区设计的洪水监测系统,该系统整合了Sentinel-1 SAR数据、Sentinel-2光学影像和WorldPop人口数据等多源遥感数据。系统通过VV极化SAR数据的水体提取算法(阈值-13dB)实现洪水范围监测,结合10米分辨率的光学影像进行可视化验证,并利用100米分辨率人口数据评估受灾人口。系统提供完整的技术实现,包括研究区加载、遥感数据处理、日期选择界面和洪水变化检测等功能模块,为灾害应急响应提供科学依据。

此星光明博客 191

如何判断链表有环

如何判断单链表是否存在环 有一个单向链表,链表当中有可能出现“环”,就像题图这样。如何用程序判断出这个链表是有环链表? 不允许修改链表结构。 时间复杂度O(n),空间复杂度O(1)。方法一、穷举遍历 方法一:首先从头节点开始,依次遍历单链表的每一个节点。每遍历到一个新节点,就从头节点重新遍历新节点之前的所有节点,用新节点ID和此节点之前所有节点ID依次作比较。如果发现新节点之前的所有节点当中存在...

少年夜雨行的专栏 7283

FPGA 学习笔记:Vivado 工程更改FPGA 型号

FPGA 学习笔记:Vivado 工程更改FPGA 型号

坚韧与专注 1万+

TC3XX - MCAL知识点(二十四):UART MCAL配置及代码实战

UART驱动程序负责按照UART协议提供通信服务。ASCLIN模块为异步通信提供硬件支持,实现UART协议。UART驱动程序提供了配置、初始化、数据传输、接收等功能,还提供了中止传输和中止接收 abort等可选特性。软硬件匹配关系如下:UART驱动程序使用ASCLIN进行数据的传输和接收。驱动程序使用的关键硬件功能特性是:1、全双工异步工作模式2、支持半双工工作模式3、16字节的TXFIFO4、16字节的RXFIFO5、2 ~ 16位数据帧6、校验位生成/检查7、一个或两个停止位。

梦想技术家 1831

判断两个链表是否相交和一个单链表是否有环及环的链接点(转)

给定一个单链表,只给出头指针h: 1、如何判断是否存在环? 2、如何知道环的长度? 3、如何找出环的连接点在哪里? 4、带环链表的长度是多少?   解法: 1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。 2、对于问题2,记录下问题1的碰

lzy2014的专栏 1214

工业预测性维护实战:振动分析+Transformer预警系统构建指南

摘要:本文聚焦工业设备预测性维护难题,提出基于振动分析与Transformer模型的全栈解决方案。通过低成本硬件选型(单传感器¥380)实现设备振动信号实时采集,利用边缘计算单元完成特征工程(RMS、峰度、峰值频率提取),并在云端部署Transformer时序模型进行异常预警。某风电龙头企业实践显示,系统将故障误报率从38%降至6%,维护成本降低58%,非计划停机时长减少87%。文中提供完整的边缘端特征提取代码、云端模型架构及实施流程,适配ISO 13373振动分析标准,为制造业设备健康管理提供可复用的工程

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 625

判断单链表是否有环及环的链接点

问题: 给定一个单链表,只给出头指针h: 1、如何判断是否存在环? 2、如何知道环的长度? 3、如何找出环的连接点在哪里? 4、带环链表的长度是多少?   解法: 1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。 2、对于问题2,记录下问题1的碰撞点p,从碰撞点开

Forward 478

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

判断一个单链表是否有环及环的链接点

一种方法是设置两个指针指向单链表的head, 然后开始遍历,第一个指针走一步,第二个指针走两步,如果没有环,它们会直接走到底,如果有环,这两个指针一定会相遇。该方法的实现代码如下,程序中找出了环的起始位置:

赶路 572

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

笔试题:如何判断单链表是否存在环

给定一个单链表,只给出头指针h:1、如何判断是否存在环?2、如何知道环的长度?3、如何找出环的连接点在哪里?4、带环链表的长度是多少? 解法:1、对于问题1,使用追赶的方法,设定两个指针slow、fast,从头指针开始,每次分别前进1步、2步。如存在环,则两者相遇;如不存在环,fast遇到NULL退出。2、对于问题2,记录下问题1的碰撞点p,slow、fast从该点

liuxialong的专栏 3万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

判断单链表中是否有环 | 判断两个单链表是否相交

目录 一.判断单链表是否存在环 1.判断一个单链表中是否存在环 2.寻找环的连接点 3.如何获取环的长度 4.如何将带环的单链表变为普通的单链表 二.判断两个无环单链表是否相交 1.方法一 利用两个相交链表尾节点相等的属性 2.方法二 利用栈 3.方法三 利用环 一.判断单链表是否存在环 首先我们来看一下,什么叫做单链表中存在环,即下图中所示的这种情况。 其中,我们将节点5称为连接点,即这个单链表中环开始的那个节点。 1.判断一个单链表中是否存在环 定义两个指针,即快指...

ThinPikachu的博客 986

判断单链表是否有环

判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?    相关题目:  (1)找出单链表的倒数第 4个元素。找出单链表的中间元素。  (2)判断两个单链表是否相交,若两个单链表相交,计算相交点。  解题思路:  (1)判断是否有环。采用快慢指针的思路,一个指针一次移动一个结点,另一个指针移动两个结 点。  如果有环,则进入环后,快指针肯定可以追赶上慢指针,这样就会出现两

陈曦的专栏 1万+

【Java数据结构】判断单链表是否有环,并且找出环的入口

一:判断是否有环 思路:使用快慢引用法解决 是否有环 假设链表是一个有环链表,且由f指向c构成环。那么 使用两个指针 A 和 B,让两指针同时向后遍历 而且B的遍历速度是A的两倍,呢么如果是有环的话,B终究会追上A。因此我们可以 以AB是否相遇作为判断是否有环的必要条件。 下面是图...

懂技术的猫 4638
上一篇: C++引用和指针的对比
下一篇: 多线程还是多进程的选择及区别
Solid7
博客等级 码龄11年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值