您的位置:首页 > 其它

判断两个链表是否相交(考虑带环与不带环)

2017-07-17 00:50 288 查看

1.不考虑带环的情况,若相交,求交点

解法一:如果两个链表都无环,则可以把第二个链表接在第一个链表后面,如果得到的链表有环,则说明这两个链表相交。这里如果有环,则第二个链表的表头一定在环上,只需要从第二个链表开始遍历,看是否会回到起点即可判断。假设两个链表长度分别为m和n,则时间复杂度为O(m+n)



解法二:若两个链表都无环且交于一点,那么最后一个节点一定是共有的。可以先遍历第一个链表,记录最后一个节点,再遍历第二个链表,将其最后一个节点与第一个链表的最后一个节点比较,若相同,则相交。时间复杂度也为O(m+n)。

代码如下:(结点的结构体)

typedef int DataType;   //结点的结构体
typedef struct LinkNode
{
DataType data;
LinkNode* next;
}Node,*pNode;


bool IsCrossLink(pNode pHead1, pNode pHead2) //判断两链表是否相交(假设链表不带环)
{
if (pHead1==NULL || pHead2==NULL)
return false;
pNode pH1 = pHead1;
pNode pH2 = pHead2;
while (pH1->next != NULL)
pH1 = pH1->next;
while (pH2->next != NULL)
pH2 = pH2->next;
if(pH1 == pH2)
return true;
else
return false;
}


扩展问题:

求两个链表相交的第一个节点。

int Size(pNode pHead)//链表有效元素的个数
{
int count = 0;
pNode pCur = pHead;
while (pCur != NULL)
{
count++;
pCur = pCur->next;
}
return count;
}

pNode GerCrossNode(pNode pHead1, pNode pHead2) //获得相交结点
{
if (!IsCrossLink(pHead1,pHead2))//不相交,直接返回
return NULL;
pNode pH1 = pHead1; //指向第一个链表
pNode pH2 = pHead2; //指向第二个链表
int size1 = Size(pHead1); //第一个链表长度
int size2 = Size(pHead2); //第二个链表长度
int steps = size2 - size1;
if (steps > 0)  //使两个指针到交点的相同
{
while (steps--)
pH2 = pHead2->next;
}
else
{
while (steps++)
pH1 = pHead1->next;
}
while (pH1 != pH2)
{
pH1 = pH1->next;
pH2 = pH2->next;
}
return pH1;
}


2.考虑是否带环

首先要判断有头指针的单链表是否有环。

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

pNode IsRoundLink(pNode pHead) //判断链表是否带环
{
if (pHead == NULL)
return NULL;
pNode pFast = pHead;
pNode pSlow = pHead;

while (pFast != NULL && pFast->next != NULL)
{
pFast = pFast->next->next;
pSlow = pSlow->next;

if (pFast == pSlow)
{
return pFast;
}
}
return NULL;
}


若两个都无环,回到第一种情况;

若一个有环,一个无环,不用判断,两链表肯定不相交;

若两个都有环,判断第一个链表的碰撞点(fast与slow相遇的节点,这里是为了方便判断是否带环的函数若带环将碰撞点传回来)是否出现在第二个链表的环中,如果在,则相交。(相交时,环必定是两链表共有的。)

寻找带环单链表的环入口节点的方法:

碰撞点到交点的距离=头指针到交点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是交点。

pNode GetEnterNode(pNode pHead, pNode pMeet) // 获得环的入口点
{
if (pMeet == NULL || pHead == NULL)
return NULL;
pNode pH = pHead;
while (pH != pMeet)
{
pH = pH->next;
pMeet = pMeet->next;
}
return pMeet;
}


若有环,计算出两链表的长度len1、len2(环的长度与环的头指针到交点长度之和就是链表长度)。

如果len1>len2,则第一个链表的指针先走len1-len2,然后第二个链表的指针开始走,两者相遇的点就是相交点;

如果len2>len1,则第二个链表的指针先走len2-len1,然后第一个链表的指针开始走,两者相遇的点就是相交点。

求环的长度的方法:

让指针从碰撞点开始走,再次碰撞所走过的操作数就是环的长度。

int CircleLen(pNode pMeet)  //获得环的长度
{
int length = 1;
if (pMeet == NULL)
return -1;
pNode pCur = pMeet->next;
while (pCur != pMeet)
{
pCur = pCur->next;
length++;
}
return length;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐