判断两个链表是否相交?若相交求出交点?(两个链表均带环)

关于链表相交的问题

如何判断链表是否带环,以及如何求环的入口点

判断两个带环单链表是否相交:
  分别判断两个单链表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;
}

猜你喜欢

转载自blog.csdn.net/zhao_miao/article/details/81747303