链表环问题总结

来源:互联网 发布:中国数据库排名 编辑:程序博客网 时间:2024/06/07 09:46

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

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

2、如何知道环的长度?

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

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


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

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

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. bool IsExitsLoop(slist *head)  
  2. {  
  3.     slist *slow = head, *fast = head;  
  4.   
  5.     while ( fast && fast->next )   
  6.     {  
  7.         slow = slow->next;  
  8.         fast = fast->next->next;  
  9.         if ( slow == fast ) break;  
  10.     }  
  11.   
  12.     return !(fast == NULL || fast->next == NULL);  
  13. }  

2、如何知道环的长度?

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


3、如何找出环的连接点(入口)在哪里?

设环的长度为r,链表长度为L,节点相遇时slow走了s步,fast在环中转了n圈,入口环与相遇点距离为x,起点到环入口点的距离为a。slow走一步,fast走两步。
因此
2s = nr + s
s = nr


s = a + x
L = a + r => r = L – a

a + x = nr
a = nr - x


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

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. slist* FindLoopPort(slist *head)  
  2. {  
  3.     slist *slow = head, *fast = head;  
  4.   
  5.     while ( fast && fast->next )   
  6.     {  
  7.         slow = slow->next;  
  8.         fast = fast->next->next;  
  9.         if ( slow == fast ) break;  
  10.     }  
  11.   
  12.     if (fast == NULL || fast->next == NULL)  
  13.         return NULL;  
  14.   
  15.     slow = head;  
  16.     while (slow != fast)  
  17.     {  
  18.          slow = slow->next;  
  19.          fast = fast->next;  
  20.     }  
  21.   
  22.     return slow;  
  23. }  

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

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


参考:

http://blog.sina.com.cn/s/blog_725dd1010100tqwp.html

http://blog.csdn.net/liuxialong/article/details/6555850

http://snprintf.net/archives/575


0 0