关于链表相交的问题
- 如果两个链表均不带环
判断两个不带环单链表是否相交?若相交求交点 - 如果一个链表带环,一个链表不带环。两个链表不可能相交!
- 如果两个链表均带环:(有以下两种相交的情况)
判断两个带环单链表是否相交:
分别判断两个单链表p1,p2是否带环,返回快慢指针的交点(此交点必在环内)meet1,meet2,一个指针不动,另一个指针向后移动一圈,若相遇则证明meet1和meet2在一个环内,即证明两个带环单链表相交。
#define DataType int
typedef struct Node{
DataType data;
struct Node* next;
}linklist;
void LinklistIntersectOP(linklist *p1, linklist *p2)
{
linklist *cur1 = NULL;
linklist *cur2 = NULL;
linklist *p = NULL;
if (p1==NULL&&p2==NULL)
{
return;
}
cur1 = CircleLinkList(p1);//cur1为p1快慢指针的相遇点
cur2 = CircleLinkList(p2);//cur2为p2快慢指针的相遇点
//cur2不动,cur1走一圈,若cur1和cur2相遇则有环
while (cur1->next != cur1)
{
if (cur1 == cur2)
{
//两个链表相交,求交点
LinkListpointOP(p1, p2);
return;
}
cur1 = cur1->next;
}
}
其中CircleLinkList(判断是否带环)函数为:
linklist* CircleLinkList(linklist *head)
{
linklist *fast = NULL;
linklist *slow = NULL;
if (head == NULL)
return NULL;
fast = head;
slow = head;
while (fast != NULL&&fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return fast;
}
}
return NULL;
}
判断两个带环单链表的相交:
- 首先判断两个单链表是环内相交还是环外相交。
若两个单链表环的入口点为同一点,则环外相交。
若两个单链表环的入口点不是同一点,则环内相交。 - 若单链表环外相交。
- 若单链表环内相交则交点为任一单链表的入口点。
void LinkListpointOP(linklist *p1, linklist *p2)
{
linklist *meet1 = CircleLinkList(p1);//p1快慢指针的相遇点
linklist *meet2 = CircleLinkList(p2);//p2快慢指针的相遇点
linklist *Ent1 = GetCircleEnter(p1, meet1);//p1的入口点
linklist *Ent2 = GetCircleEnter(p2, meet2);//p2的入口点
if (Ent1 == Ent2)//环外相交
{
printf("两个带环单链表环外相交!\n");
LinkListOutpoint(p1, p2, meet1);
}
else //环外相交
{
printf("两个带环单链表环内相交!\n");
printf("交点为:%d \n", Ent1->data);
}
}
LinkListOutpoint(环外相交的做法):
void LinkListOutpoint(linklist *p1, linklist *p2,linklist *meet)
{
int count = 0;
int count1 = 0;
int count2 = 0;
linklist *cur1 = p1;
linklist *cur2 = p2;
//p1的长度
while (cur1 != meet)
{
count1++;
cur1 = cur1->next;
}
//p2的长度
while (cur2 != meet)
{
count2++;
cur2 = cur2->next;
}
cur1 = p1;
cur2 = p2;
//p1与p2的差
count = count1 - count2;
if (count >= 0)
{
//p1先走count步
while (count--)
{
cur1 = cur1->next;
}
while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
printf("交点为:%d\n", cur1->data);
}
else
{
while (count--)
{
cur2 = cur2->next;
}
while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
printf("交点为:%d\n", cur1->data);
}
}
GetCircleEnter(环的入口点):
linklist * GetCircleEnter(linklist *head, linklist * meet)
{
linklist *pre = NULL;
linklist *ret = NULL;
if (head == NULL)
return NULL;
pre = head;
ret = meet;
while (pre != ret)//meet为相遇点,head和meet一起向后移动,直到相等
{
pre = pre->next;
ret = ret->next;
}
return ret;
}