判断单链表是否带环?若带环,求环的长度?返回环的入口点?

判断单链表是否带环,可以先定义两个指向链表首节点的快慢指针,快指针每次沿着链表向后走两次,慢指针向后走一次,若快慢指针相遇说明链表带环。
环的长度:在快慢指针第一次相遇时记录相遇点,让慢指针继续走,再次经过相遇点时经过的长度便是环的长度。
入口点:假设从链表的头到环的入口点长度为L,从入口点到第一次相遇点的长度为d,从第一次相遇点到入口点的长度为x,根据快指针走过的长度是慢指针的两倍可以得到 2*(L+d)=L+n(x+d)+d,其中n为快指针经过环的圈数(n>=0),化简得到,L=x+(n-1)(x+d),其中x+d为环的长度。也就是说,定义一个指针从第一次相遇点开始走,另一个指针从链表头开始走,后者走到环的入口时,前者刚好也走到环的入口(有可能已经经过好几次)。根据这个关系,即可求出环的入口点。

typedef int DataType;

typedef struct SListNode
{
    struct SListNode* _next;
    DataType _data;
}SListNode;
SListNode* SListIsCycle(SListNode* list)  
{
    assert(list);
    SListNode* fast = list;
    SListNode* slow = list;
    SListNode* cur1 = list;
    SListNode* cur2;
    SListNode* next;
    int count = 1;
    while (fast->_next!=NULL)
    {
        slow = slow->_next;
        fast = fast->_next;
        fast = fast->_next;
        if (slow == fast)
        {
            cur2 = fast;
            next = cur2->_next;
            while (next != cur2)
            {
                next = next->_next;
                count++;
            }
            printf("环的长度为%d\n", count);
            break;
        }
    }
    if (fast->_next == NULL)
    {
        return NULL;
    }
    while (cur1 != fast)
    {
        cur1 = cur1->_next;
        fast = fast->_next;
    }
    return cur1;
}

猜你喜欢

转载自blog.csdn.net/smx_dd/article/details/80035186