定义:
循环链表:链表中一个节点的next指针指向先前已经存在的节点,导致链表中出现环。
问题1:判断是否有环
#include <cstring>
#include <iostream>
using namespace std;
struct node
{
char value;
node* next;
node(char rhs)
{
value = rhs;
next = NULL;
}
};
bool isLoop(node* head)
{
if (head == NULL)
{
return false;
}
node* slow = head;
node* fast = head;
while((fast!= NULL) && (fast->next != NULL))
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
break;
}
}
return !(fast == NULL || fast->next == NULL);
}
int main()
{
node A('A');
node B('B');
node C('C');
node D('D');
node E('E');
node F('F');
node G('G');
node H('H');
node I('I');
node J('J');
node K('K');
A.next = &B;
B.next = &C;
C.next = &D;
D.next = &E;
E.next = &F;
F.next = &G;
G.next = &H;
H.next = &I;
I.next = &J;
J.next = &K;
K.next = &D;
if (isLoop(&A))
{
cout<<"Loop";
}else
{
cout<<"No loop";
}
return 0;
}
问题2:找到这个环的起始点
输入: A->B->C->D->E->F->G->H->I->J->K->D
输出:D
分析:
当fast与slow相遇时, slow肯定没有遍历完链表,而fast在环内肯定循环了1圈以上。
设环的长度为r, 相遇时fast在环内走了n个整圈(n > 1),slow走了s步,fast走了2s步,则:
2s = s + nr -> s = nr
设整个链表的长度为L,环入口点与相遇点的距离为x,链表起点到环入口点的距离为a,则:
a + x = s = nr (slow走过的步数,slow为走过一圈)
a + x = (n-1)r + r = (n-1)r + (L - a) -> a = (n-1)r + (r - x)
(r - x) 为相遇点到环入口点的距离; 因此,链表头到环入口点的距离 等于 (n-1)个环循环 + 相遇点到环入口的距离。
我们从链表头和相遇点分别设置一个指针,每次各走一步,则两个指针必定相遇,且第一个相遇点为环入口点。
#include <cstring>
#include <iostream>
using namespace std;
struct node
{
char value;
node* next;
node(char rhs)
{
value = rhs;
next = NULL;
}
};
node* isLoop(node* head)
{
if (head == NULL)
{
return false;
}
node* slow = head;
node* fast = head;
while((fast!= NULL) && (fast->next != NULL))
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
break;
}
}
if (fast == NULL || fast->next == NULL)
{
return NULL;
}
// currently, the list is looped
slow = head;
while(slow != fast)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
int main()
{
node A('A');
node B('B');
node C('C');
node D('D');
node E('E');
node F('F');
node G('G');
node H('H');
node I('I');
node J('J');
node K('K');
A.next = &B;
B.next = &C;
C.next = &D;
D.next = &E;
E.next = &F;
F.next = &G;
G.next = &H;
H.next = &I;
I.next = &J;
J.next = &K;
K.next = &D;
node* p;
if ((p= isLoop(&A))!= NULL)
{
cout<<"Loop, the interaction node is "<<p->value;
}else
{
cout<<"No loop";
}
return 0;
}