!参考网络资料和自己的理解整理而得
题目:
1. 如何判断是否有环?
答:如果有两个头结点指针,一个走的快,一个走的慢,那么若干步以后,快的指针总会超过慢的指针一圈而相遇。
感性理解:就像是时钟的分针以及秒针一样。
定量分析:当fast与slow相遇时,show肯定没有走完链表,而fast已经在还里走了n(n>= 1)圈。假设slow走了s步,那么fast走了2s步。fast的步数还等于s走的加上环里转的n圈,所以有:2s = s + nr。因此,s = nr。
2. 如何计算环的长度?
答:第一次相遇(超一圈)时开始计数,第二次相遇时停止计数。
定量分析:当fast与slow第一次相遇时,s=nr。当fast与slow第二次相遇时,s'=(n+1)r(即一个走多r,一个走多2r)。所以可以得到r=s-s'。
3. 如何判断环的入口点?
答:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,相遇的那个点就是连接点。
定量分析:设整个链表长为L,入口据相遇点X,起点到入口的距离为a。因为slow指针并没有走完一圈,所以:a + x = s,代入第一步的结果,有:a + x = s。因此,起点 至 a点 从起点共走了a步到达a点;碰撞点 至 a点 从碰撞点共走了a步到达2a+x=2s-x=nr+s-x=nr+a<==>a点;此时,两个指针重合。
4. 如何判断两个链表(不带环)是否相交?
答:
方法一:将其中的一个链表首尾相连,然后判断另一个链表是否带环即可。
方法二:同时遍历两条链表,并查看结点是否重合。
5. 如何判断两个链表(带环)是否相交?
答:从相遇点开始利用一个记录指针在其中一个链表环内走一圈,看是否会与另外一个链表的某个结点重合。
C++代码:
#include <iostream>
using namespace std;
struct Node{
int data;
Node* next;
};
Node* testCylic(Node* h1){
Node *p1 = h1, *p2 = h1;
while (p1 != NULL&&p2->next != NULL){
p1 = p1->next;
p2 = p2->next->next;
if (p1 == p2){
return p1;
}
}
return NULL;
}
int loopLength(Node* h1){
Node *p1 = h1, *p2 = h1;
bool first = true;
int length = 0;
while (p1 != NULL&&p2->next != NULL){
p1 = p1->next;
p2 = p2->next->next;
if (p1 == p2 && first){
first = false;
}
if (p1 == p2&& !first)
break;
if (!first)
length++;
}
return length;
}
Node* findLoopEntrance(Node* h1){
Node* p1 = testCylic(h1);
if (p1 == NULL || h1==NULL)
return NULL;
Node* p2 = h1;
while (p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
// if there is no cycle.
bool isJoinedSimple(Node *h1, Node *h2){
Node* p1 = h1;
Node* p2 = h2;
while (p1->next != NULL)
p1 = p1->next;
while (p2->next != NULL)
p2 = p2->next;
return p1 == p2;
}
// if there could exist cycle
bool isJoined(Node *h1, Node *h2){
Node* cylic1 = testCylic(h1);
Node* cylic2 = testCylic(h2);
if (cylic1 == NULL && cylic2 == NULL)
return isJoinedSimple(h1, h2);
if ((cylic1 == NULL&&cylic2 != NULL) || (cylic1 != NULL&&cylic2 == NULL))
return false;
Node* p1 = cylic1;
while (1){
if (p1 == cylic2 || p1 == cylic2->next)//The node in link1 is equal to cylic2
return true;
p1 = p1->next->next;
cylic1 = cylic1->next;
if (p1 == cylic1) //Traverse all the nodes in link1
return false;
}
}