【问题标题】:Floyd algorithm - Cycle Detection - not terminating for the exampleFloyd 算法 - 循环检测 - 示例不终止
【发布时间】:2015-07-20 09:44:21
【问题描述】:

有人可以用这个例子解释弗洛伊德算法吗?它对我来说并没有终止,算法实现是否完整?

我的代码有问题吗?代码如下:

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;
}

对画的不好表示歉意!

【问题讨论】:

  • 如果您找到匹配项,我认为您退出第一个 while 循环以快速。兔子应该总是跳两次。

标签: c++ algorithm linked-list cycle floyd-cycle-finding


【解决方案1】:

你的方法的问题是你退出第一个while循环太快了。如the algorithm states,兔子跳两次,乌龟跳一次,只有在这些跳之后,你可以检查。所以算法应该是:

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(我同意这不是很好的 C++ 代码,但仅用于演示)。更简洁的版本可以在here找到。

【讨论】:

  • 只有当 slowptr 和 fastptr 相同时,第一个循环才被打破,对吗?即使根据您的算法,第二个循环也永远不会终止,对吗?
  • 好吧,正如已经说过两次(在答案中也是如此),您应该检查兔子的两跳和乌龟的一跳。您的算法在每次更新时都会进行这些检查。这就是为什么我将if 放在评论中。
  • 一个小疑问 - slowptr 必须在 if(fastptr && slowptr && fastptr == slowptr) 之前或之后增加?在检查之前,fastptr 必须比 slowptr 提前两倍,对吗?所以slowptr必须在if条件之后移动?
  • 不,if 必须在慢速指针跳跃之后进行评估。如代码中所述。如果您查看 wiki 页面,您可以在 while 循环中进行检查。由于您使用while 循环进行空检查,因此您可以通过将条件放在底部的if 循环中来解决它。
【解决方案2】:

您的第二个循环是问题所在。当你退出第一个循环时,slowptr 和 fastptr 都指向 12。然后你将 slowptr 重置为 10,然后进入第二个循环。

在第二个循环中,slowptr 和 fastptr 在 10 和 14 之间交替,并且永远不会相同。这就是循环永远不会结束的原因。

【讨论】:

    猜你喜欢
    • 2012-07-25
    • 2016-01-18
    • 2017-05-29
    • 1970-01-01
    • 2011-09-17
    • 2014-05-09
    • 2015-01-31
    • 2012-06-18
    • 2011-11-15
    相关资源
    最近更新 更多