先简单分析:
两个单链表相交分如图几种情况:
实现如下:
//判断链表是否带环,若带环求入口点
PNode IsCircleList(PNode *pHead)
{
if (NULL == *pHead || NULL == pHead)
{
return NULL;
}
PNode pFast = (*pHead)->next->next;
PNode pSlow = (*pHead)->next;
while (pFast != pSlow && NULL != pFast && NULL != pFast->next)
{
pFast = pFast->next->next;
pSlow = pSlow->next;
}
if (NULL == pFast || NULL == pFast->next)
{
return NULL;
}
pSlow = *pHead;
while (pSlow != pFast)
{
pSlow = pSlow->next;
pFast = pFast->next;
}
return pSlow;
}
//求链表结点个数
size_t Size(PNode pHead)
{
if (NULL == pHead)
{
return 0;
}
//先判断是不是带环的,带环就获取入口点
PNode pCur = IsCircleList(&pHead);
size_t count = 0;
//不带环,遍历一次,计算出结点个数
if (NULL == pCur)
{
while (NULL != pHead)
{
pHead = pHead->next;
count++;
}
}
else
{
//先计算环外的长度
PNode pTmp = pHead;
while (pTmp != pCur)
{
pTmp = pTmp->next;
count++;
}
//计算环的长度
pTmp = pTmp->next;
count++;
while (pTmp != pCur)
{
pTmp = pTmp->next;
count++;
}
}
return count;
}
//两个不带环单链表求交点
PNode IsIntersectTowListNoCircle(PNode *pHead1, PNode *pHead2)
{
if (NULL == pHead1 && NULL == *pHead1)
{
return NULL;
}
if (NULL == pHead2 && NULL == *pHead2)
{
return NULL;
}
PNode pCur1 = *pHead1;
PNode pCur2 = *pHead2;
int idx = Size(pCur1) - Size(pCur2);
//idx作为计数器,让长的链表先移动idx个结点
if (idx > 0)
{
while (idx--)
{
pCur1 = pCur1->next;
}
}
else
{
while (idx++)
{
pCur2 = pCur2->next;
}
}
//然后他们一起向后移动,知道他们指向同一个交点
while (pCur1 != pCur2)
{
pCur1 = pCur1->next;
pCur2 = pCur2->next;
}
return pCur1;
}
//判断两个链表是否相交,若相交求交点
PNode IsIntersectTowList(PNode *pHead1, PNode *pHead2)
{
if (NULL == pHead1 && NULL == *pHead1)
{
return NULL;
}
if (NULL == pHead2 && NULL == *pHead2)
{
return NULL;
}
PNode pCur1 = *pHead1;
PNode pCur2 = *pHead2;
pCur1 = IsCircleList(pHead1);
pCur2 = IsCircleList(pHead2);
//如果两个链表为不带环单链表
if (NULL == pCur1 && NULL == pCur2)
{
return IsIntersectTowListNoCircle(pHead1, pHead2);
}
//如果两个链表带环
if (NULL != pCur1 && NULL != pCur2)
{
//入口点相同说明他们在入口点或者入口点之前就相交,相当于单链表的相交求解
if (pCur1 == pCur2)
{
return IsIntersectTowListNoCircle(pHead1, pHead2);
}
//如果是环内相交,也就是入口点不同(也可能两个带环链表不相交)
else
{
//因为pCur1是第一个相遇点,如果他们是相交的则从pCur1下一个结点开始遍历,在回到pCur1之前肯定能找到pCur2若找不到,则说明没有相交
PNode pTmp = pCur1->next;
while (pTmp != pCur2 && pTmp != pCur1)
{
pTmp = pTmp->next;
}
//回到自己说明没有相交
if (pTmp == pCur1)
{
return NULL;
}
//如果找到pCur2则返回一个入口点,因为整个环都是他们的交点
else
{
return pCur1;
}
}
}
return NULL;
}