转:有环链表交点判断

http://blog.csdn.net/xie376450483/archive/2011/03/13/6247071.aspx

 

 

今天要讲的和那篇类似,就是给定两个链表,如何来判断这两个链表相交了

首先应该分两种情况考虑,第一:这两个链表本身都没有环。  第二:这两个链表本身都有环

 

首先讲都没有环的情况,如下图

方法很多,不过我想最简单的方法是遍历第一个链表,然后遍历到最后一个节点时候,用一个指针把节点地址记录下来

然后再来遍历第二个链表,同样记录下最后一个链表的地址,如果两个指针的指向一样,那么就可以判断出两个链表相交了

然后再来判断他们的交点

把第一个链表的尾节点指向第二个链表的头结点,这样就形成了一个6字型的环链表,利用我们前面那篇文章讲的方法就可以求出相交节点

 

然后说第二种情况

两个链表本身都有环,首先我们应该知道如果一个链表有环,一个链表没有环,那么他们肯定不想交,自己画画图就明白了,不多说

现在判断出两个链表都有环,那么怎么来判断相交了呢?

方法是遍历利用前面的方法找到第一个链表的环点,然后将环断开(当然不要忘记了保存它的下一个节点),然后再来遍历第二个链表,如果发现第二个链表从有环变成了无环,那么他们就是相交的嘛,否则就是不相交的了。

 

在判断出来两个有环的链表有交点后,然后来找出相交的节点,这时候又分了两种情况,相交点在环之前还是相交点在环之后,这样讲不严谨,应该是对一个链表来讲相交点是在另一个链表的环之前还是之后。

方法如下

首先找到两个链表的环点,利用前面那篇文章的方法,假设两个链表的环点分别是p1,p2 加入p1==p2 说明相交点是在环点之前,

如下图:

这时候我们可以从环点断开,同样记得保存下一个节点,然后把环点指向其中一个链表的表头,这样就把问题转换成前面6字形环形链表的相交节点问题

 

如果两个链表的相交情况如下图呢?

那这样就很那说哪个是交点了,因为有两个交点,其实不叫两个交点,是相对于l1来讲交点是l2的环点,相对于l2来讲交点是l1的环点

而环点同样是前面的方法得到的。

 

 

 

    1. template<typename T>  
    2. ListNode<T>* FindFirstCommonNode_2(ListNode<T>* pHead1, ListNode<T>* pHead2)  
    3. {  
    4.     ListNode<T>* pEntrance1 = FindRingEntrance(pHead1);  
    5.     ListNode<T>* pEntrance2 = FindRingEntrance(pHead2);  
    6.   
    7.     ListNode<T>* pResult = NULL;  
    8.     if(pEntrance1 == pEntrance2)  
    9.     {  
    10.         ListNode<T>* pTemp1 = NULL, *pTemp2 = NULL;  
    11.         if(pEntrance1)  
    12.         {  
    13.             // 环入口点已经相交,寻找第一交点。  
    14.             pTemp1 = pEntrance1->pNext;  
    15.             pTemp2 = pEntrance2->pNext;  
    16.             pEntrance1->pNext = NULL;//断裂后变成两个单链表的方法来计算   
    17.             pEntrance2->pNext = NULL;  
    18.             pResult = FindFirstCommonNode(pHead1, pHead2);  
    19.             pEntrance1->pNext = pTemp1;  
    20.             pEntrance2->pNext = pTemp2;  
    21.         }  
    22.         else  
    23.         {  
    24.             // 无环单链表求第一交点  
    25.             pResult = FindFirstCommonNode(pHead1, pHead2);  
    26.         }  
    27.   
    28.         return pResult;  
    29.     }  
    30.     else if(pEntrance1 == NULL || pEntrance2 == NULL)  
    31.     {  
    32.         // 一有环,另一个无环,无交点  
    33.         return NULL;  
    34.     }  
    35.     else  
    36.     {  
    37.         // 入口点不同的两环求交点  
    38.         pResult = pEntrance1->pNext;  
    39.         while(pResult != pEntrance2 && pResult != pEntrance1)  
    40.         {  
    41.             pResult = pResult->pNext;  
    42.         }  
    43.           
    44.         return pResult == pEntrance2 ? pResult : NULL; //不确定两个环链表是否相交,否则两个环结点任一个都是结果  
    45.     }  
    46. }  
posted @ 2013-10-26 12:03  天天向上...  阅读(575)  评论(0编辑  收藏  举报