判断链表中有环

1.第一种实现

bool List_is_loop(slist *head)

{

  slist *slow=head;

  slist *fast=head;

 

  while(NULL!=fast && NULL!=fast->next)

  {

    slow=slow->next;

    fast=fast->next->next;

    if(slow==fast) break;

  }

  

  // 无环:当链表个数为基数时fast->next总是为NULL;当链表个数为偶数时fast总是为NULL;

  return !(fast==NULL || fast->next==NULL);

}

 

2.第二种实现

bool List_is_loop(slist *head)

{

  slist *slow=head;

  slist *fast=head;

 

  if( NULL==slow || NULL==slow->next)

    return false;

  

  do

  {

    slow=slow->next;

    fast=fast->next->next;

  }while(NULL!=fast && NULL!=fast->next && slow!=fast)

 

  if(slow==fast)

  {

    return true;

  }

  else

  {

    return false;

  }

}

 

3. 若链表存在环,找到环的入口点

假设 slow走了s步,则fast走了2s步(fast的步数还等于s加上在环上多转的n圈),设环长为r,则:
2s=s+nr
s=nr
设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a,则
a+x=s=nr
a+x=(n-1)r+r=(n-1)r+L-a
a=(n-1)r+(L-a-x)
(L-a-x)为相遇点到环入口点的距离。由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点。于是可以从链表头和相遇点分别设一个 指针,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。

     1---2---3---4--5--6--7
                    |            |

                    -----------

   如上图所示:在节点5相遇;1到4的距离为a;4到5的距离为x;环长度为r;

 

slist* List_is_loop_enter(slist *head)

{

  slist *slow=head;

  slist *fast=head;

 

  while(NULL!=fast && NULL!=fast->next)

  {

    slow=slow->next;

    fast=fast->next->next;

    if(slow==fast) break;

  }

  

  // 无环:当链表个数为基数时fast->next总是为NULL;当链表个数为偶数时fast总是为NULL;

    if(fast==NULL || fast->next==NULL)

    return NULL;

  

       slow=head;

  while( slow!=fast)

  {

    slow=slow->next;

    fast=fast->next;

  }  

       return slow;

}

 

4.计算环长度

从环入口进行一个循环即可。

int List_is_loop_length(slist *head)

{

  int length=0;

  slist *slow=head;

  slist *fast=head;

 

  while(NULL!=fast && NULL!=fast->next)

  {

    slow=slow->next;

    fast=fast->next->next;

    if(slow==fast) break;

  }

  

  // 无环:当链表个数为基数时fast->next总是为NULL;当链表个数为偶数时fast总是为NULL;

    if(fast==NULL || fast->next==NULL)

    return 0;

  

       slow=head;

  while( slow!=fast)

  {

    slow=slow->next;

    fast=fast->next;

  }  

       

  //从环入口开始循环

  slist* p=slow;

  do

  {

    p=p->next;

    length++;

  }while(p!=slow)

 

  return length;

}

 

posted @ 2015-04-15 21:16  hy1hy  阅读(159)  评论(0编辑  收藏  举报