Floyd 算法 - 循环检测 - 不终止的例子
Floyd algorithm - Cycle Detection - not terminating for the example
有人可以用这个例子解释弗洛伊德算法吗?它对我来说没有终止,算法实现是否完整?。
我的代码有问题吗?代码如下:
Node* FindLoopBegin(Node *head){
Node *slowptr = head,*fastptr = head;
bool LoopExists = false;
while(slowptr && fastptr){
fastptr = fastptr->next;
if(fastptr == slowptr) {LoopExists = true;break;}
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
if(fastptr == slowptr) {LoopExists = true;break;}
slowptr = slowptr->next;
}
if(LoopExists) {
slowptr = head;
while(slowptr != fastptr){
slowptr = slowptr->next;
fastptr = fastptr->next;
}
return slowptr;
}
return NULL;
}
画得不好请见谅!
你的第二个循环是问题所在。当你退出第一个循环时,slowptr 和 fastptr 都指向 12。然后你将 slowptr 重置为 10,并进入第二个循环。
在第二个循环中,slowptr 和 fastptr 在 10 和 14 之间交替,并且永远不会相同。这就是循环永远不会结束的原因。
您的方法的问题是您退出第一个 while 循环 太早了。如the algorithm states,兔子跳2次,乌龟跳1次,只跳了次,就可以查了。所以算法应该是:
while(slowptr && fastptr){
fastptr = fastptr->next;
//if(fastptr == slowptr) {LoopExists = true;break;} //remove the if loop
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
//move the if loop down
if(fastptr == slowptr) {LoopExists = true;break;}
}
您也可以在相等性检查之前进行 NULL
检查:
while(slowptr && fastptr){
fastptr = fastptr->next;
//if(fastptr == slowptr) {LoopExists = true;break;} //remove the if loop
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
//move the if loop down
if(fastptr && slowptr && fastptr == slowptr) {LoopExists = true;break;}
}
或更清洁的版本:
do {
fastptr = fastptr->next;
if(fastptr == NULL) {return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
} while(slowptr && fastptr && slowptr != fastptr);
if(slowptr && fastptr && slowptr == fastptr) { //loopexists
//...
}
参见 an online demo (I agree this is not nice C++ code, but only for demonstration). A cleaner version can be found here。
我的代码有问题吗?代码如下:
Node* FindLoopBegin(Node *head){
Node *slowptr = head,*fastptr = head;
bool LoopExists = false;
while(slowptr && fastptr){
fastptr = fastptr->next;
if(fastptr == slowptr) {LoopExists = true;break;}
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
if(fastptr == slowptr) {LoopExists = true;break;}
slowptr = slowptr->next;
}
if(LoopExists) {
slowptr = head;
while(slowptr != fastptr){
slowptr = slowptr->next;
fastptr = fastptr->next;
}
return slowptr;
}
return NULL;
}
画得不好请见谅!
你的第二个循环是问题所在。当你退出第一个循环时,slowptr 和 fastptr 都指向 12。然后你将 slowptr 重置为 10,并进入第二个循环。
在第二个循环中,slowptr 和 fastptr 在 10 和 14 之间交替,并且永远不会相同。这就是循环永远不会结束的原因。
您的方法的问题是您退出第一个 while 循环 太早了。如the algorithm states,兔子跳2次,乌龟跳1次,只跳了次,就可以查了。所以算法应该是:
while(slowptr && fastptr){
fastptr = fastptr->next;
//if(fastptr == slowptr) {LoopExists = true;break;} //remove the if loop
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
//move the if loop down
if(fastptr == slowptr) {LoopExists = true;break;}
}
您也可以在相等性检查之前进行 NULL
检查:
while(slowptr && fastptr){
fastptr = fastptr->next;
//if(fastptr == slowptr) {LoopExists = true;break;} //remove the if loop
if(fastptr == NULL) {LoopExists = false; return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
//move the if loop down
if(fastptr && slowptr && fastptr == slowptr) {LoopExists = true;break;}
}
或更清洁的版本:
do {
fastptr = fastptr->next;
if(fastptr == NULL) {return NULL;}
fastptr = fastptr->next;
slowptr = slowptr->next;
} while(slowptr && fastptr && slowptr != fastptr);
if(slowptr && fastptr && slowptr == fastptr) { //loopexists
//...
}
参见 an online demo (I agree this is not nice C++ code, but only for demonstration). A cleaner version can be found here。