求两个单链表的交点(可能带环)

来源:互联网 发布:程序员第一天上班想哭 编辑:程序博客网 时间:2024/06/01 09:38

先简单分析:

两个单链表相交分如图几种情况:

实现如下:

//判断链表是否带环,若带环求入口点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;}


1 0