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

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

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

2、如何知道环的长度?

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

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

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

证明:如果存在环,则他俩一定在环中相遇。

设i是走的步数,n是环的长度,

从ps走进环里开始计算,此时pf应当有一个相距于ps的距离,设为Y。

假设走了i步他俩相遇,此时ps相对于环开始节点的距离是i步,pf是Y+2i步。

相遇时快指针多走了一圈 (Y+2i)-i= n => Y+i=n =>i=n-y

所以,追上的步数i取决于进入环时y的值。y是1的时候,是追的最费劲的,需要n-1步;y是n-1的时候最容易追,1步就追上了。

Boolean has_loop(Node *head) {

  Node *pf = head; /* fast pointer */

  Node *ps = head; /* slow pointer */

  while(true) {

    if(pf && pf->next)

      pf = pf->next->next;

    else

      return FALSE;

    ps = ps->next;

    if(ps == pf)

      return TRUE;

  }

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

证明:上面的公式i=n-y,当y=0时,就是第一次相遇时开始走,i=n。

/* step 2, how long is the loop */

  int i = 0;

   do {

    ps = ps->next;

    pf = pf->next->next;

    i++;

  } while(ps!=pf)

3. 假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为n,慢指针总共走了s步,则快指针走了2s步。另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x距离),得到以下关系:
    s = a + x;
    2s = a + nr + x;
    =>a + x = nr;
    =>x = nr - a;
逆时针方向走,pf还需要走的距离是y,

y+x=tn

=>y+nr-a=tn=>y=(t-r)n+a//y的距离就是a又加了几圈

由上式可知:若在头结点和相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点,搞掂!


int FindLoopPort(Node *head) {

  Node *pf = head; /* fast pointer */

  Node *ps = head; /* slow pointer */

  while(true) {

    if(pf && pf->next)

      pf = pf->next->next;

    else

      return FALSE;

    ps = ps->next;

    if(ps == pf)

      break;

  }
  pf = head;
  int i = 0;
  while(ps != pf)
  {
	ps = ps->next;
	pf = pf->next;
	i++;
  }
  return i;
}

4. 将2和3的长度相加就是链表的长度。
 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值