判断两个单链表是否相交共有三种情况:
1,两个单链表都没有环。
2,两个单链表中 一个有环,一个没有环。
3,两个链表都有环。
看第一种情况,连个单链表相交,只能是y型相交,不可能是x型相交,理由如下,有两个链表,La,Lb,他们的交点设为p吧,假设在La中,p的前驱为pre_a,后继为next_a,在Lb中,前驱为pre_b,后继为next_b,则pre_a->next=p,pre_b_next=p,接下来看后继,p->next=next_a,p->next=next_b;然后问题就出来了,大家应该知道,一个单链表的next指针只有一个,怎么跑出两个来呢,所以两个链表相交只能值Y型相交。继续解释,两个链表从交点后的其他节点都是一样的,这样只判断最后一个节点是否相交就可以知道两个单链表时候是相交了。判断完之后,还需要寻找链表的交点。求出两个链表的长度:len_a,len_b,求出差值len(len为较大的减去较小的值)。让长的那个先走len步,之后两个链表一起走,直至有点相同的时候。下面给出独立的算法:
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
void is_intersect(LinkList La,LinkList Lb)
{
LNode *pa,*pb;
int len_a=0,len_b=0;
pa=La;
pb=Lb;
while(pa->next)
{
len_a++;
pa=pa->next;
}
len_a+=1;
while(pb->next)
{
len_b++;
pb=pb->next;
}
len_b+=1;
int temp,i=0;
pa=La;
pb=Lb;
if(len_a>len_b)
{
temp=len_a-len_b;
while(i<len_a)
{
pa=pa->next;
i++;
}
}
else
{
temp=len_b-len_a;
while(i<len_b)
{
pb=pb->next;
i++;
}
}
while(pa!=pb)
{
pa=pa->next;
pb=pb->next;
}
return pa;
}
再次,看第二种情况,一个有环,一个无环,那么两个链表肯定不相交,解释如下:
假设链表La有环,Lb无环,交点在La环点之前,那么,Lb的最后一个节点肯定在环上,要不然在延伸一下Lb也有环了。还是原来那么观点,就是一个节点只能有一个指向下个节点的指针,红点处的La的元素有下一个元素,而Lb的为NULL,则这种情况不成立。若交点在La环点之后,也不能成立,道理一样。
最后就来看第三种情况,两个链表都有环,先给出有环的和求环入口点的算法:给定一个链表,增设两个指针,一个fast,一个slow,fast每次走两步,slow每次走一步,若有环,两个节点肯定会相遇,画下图。求环入口点(环点)的理论基础:设链表长度为len,从表头到环入口点的距离为x,两个指针的交点为y,环的长度为r,从交点到入口点还需要走z步。有两个指针相交得出:y+nr=2y。fast走的步数是slow的两倍。之后x+r=len;y+z=len;整理三个实在得出:x+r=(n-1)r+z;大家可画图,n值一般情况下为2.最后x=z。这就说明,从链表头结点开始(此链表头结点有数据),到环的入口点,和fast,slow相交点到环入口点的距离一样。有了理论基础,给出算法如下:
LNode* is_cylic(LinkList L)
{
LNode *fast,*slow;
fast=L;
slow=L;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
break;
}
if(fast==NULL||fast->next==NULL)
return NULL;//if return null means this LinkList has no loop.
slow=L;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
求得环的入口点后还需要分成三种情况,一种比较特殊的是两个链表的入口点即为交点。两外两种情况看下图:
第一种情况是交点在两个环的入口点之前,第二种情况是交点在第一个链表入口点之后。前一种比较好求,即求得两个链表的入口点分别是p1,p2,if(p1==p2),说明在入口点之前,那么遍历两个表,找到入口点之前的长度,然后依照无环单链表第一个交点的方法去找 。但是如果两个入口点不一样,那么求他们的第一个交点又作何解释呢。其实可以这么理解,相对于La(入口点为p1),来说他和Lb的第一个交点即为自身的入口点,而对于Lb(入口点为p2)来说,它与La的第一个相交点为p2。(注明:此时的第一个相交点以为相对单链表的开头来说,顺序行走后的)。给出思路,解法就很简单了。