C 基于节点地址的链表循环检测

C 基于节点地址的链表循环检测,c,data-structures,linked-list,heap-memory,cycle-detection,C,Data Structures,Linked List,Heap Memory,Cycle Detection,我最近了解到: 典型的记忆总是向上生长 请参阅-> 我不太明白,但当我搜索堆在内存中是否向上增长时,我得到了类似的结果 考虑到c/c++中的上述事实,我编写了一个用于循环检测的函数,其中,如果指向structure temp的遍历指针指向的内存地址小于链表中上一个节点的内存地址,则该函数返回TRUE用于循环检测 不幸的是,下面的代码在hackerrank上没有给出期望的结果,我想知道原因。代码是: bool has_cycle(SinglyLinkedListNode* head) {

我最近了解到:

典型的记忆总是向上生长

请参阅-> 我不太明白,但当我搜索堆在内存中是否向上增长时,我得到了类似的结果

考虑到c/c++中的上述事实,我编写了一个用于循环检测的函数,其中,如果指向structure temp的遍历指针指向的内存地址小于链表中上一个节点的内存地址,则该函数返回TRUE用于循环检测

不幸的是,下面的代码在hackerrank上没有给出期望的结果,我想知道原因。代码是:

bool has_cycle(SinglyLinkedListNode* head) {
    struct SinglyLinkedListNode* temp = head;
    int x;
    if( temp == NULL )
    return false;             //FALSE indicates No cycle detected in linked list

    if( temp->next == NULL )
    return false;

    x = temp;
    while( temp->next != NULL )
    {
        temp = temp->next;
        if( x >= temp )
        return true;          //TRUE indicates Cycle detected in linked list

        x= temp;
    }

    return false;

}

我已经检查了如果堆中的内存分配是向下的,如果x,如果你创建了一个包含数千个元素的链表,并试图计算下一个列表的地址比当前列表的地址小多少倍,你会得到一些,所以这种发现是否存在循环的方法是行不通的。正确的方法是创建两个指针,其中一个指针一次移动一个列表,另一个指针一次移动两个列表,并检查每个指针的地址是否相同。

我必须同意@gtristan。我看不出内存地址比较将导致最终的周期检测解决方案。通用两节点方法是公认的解决方案,效果良好。看看这两个相关的周期检测算法:和。我最近在HackerRank上用Java语言实现了Floyd的算法,下面的代码没有什么特别之处,并且在所有测试用例中都运行良好:

// Complete the hasCycle function below.
/*
 * For your reference:
 *
 * SinglyLinkedListNode {
 *     int data;
 *     SinglyLinkedListNode next;
 * }
 *
 */
static boolean hasCycle(SinglyLinkedListNode head) {
    if (head == null) { return false; }
    SinglyLinkedListNode slow = head, fast = head;
    while (slow.next != null) {
        slow = slow.next;
        if (fast.next != null) {
            fast = fast.next;
            if (fast.next != null) {
                fast = fast.next;
                if (fast == slow) {
                    return true;
                }
            }
        }
    }
    return false;
}

希望这有帮助-

检测列表中的循环意味着在列表中查找指向列表中较早节点的下一个指针。它与节点的内存地址无关。没有循环的链表将是A->B->C->D->NULL。带有循环的链表将是A->B->C->D->B->。。。换句话说,当列表有一个循环时,遍历列表将永远找不到终点。@user3386109,我理解循环检测是什么,但我试图实现关于堆中内存分配的问题中所述的事实。我只是想知道我错在哪里。如果堆中的内存分配实际上是以升序或降序的方式进行的,那么应该使用此代码work@Seam米奇,我知道弗洛伊德的龟兔算法,我知道这个解决方案会奏效。你的回答仍然不能回答我的问题。当每次对malloc的consequentive调用都会由于堆中的内存增长而给出更大的内存地址值时,那么任何下一个地址减去上一个节点的地址都表明我们已经返回,即一个循环。请澄清我的疑问。为什么会出现下一个节点的内存地址少于当前节点的情况?若您遵循堆中的内存分配,那个么它会向上增长,所以添加到链表中的每个新节点的内存地址都会比以前添加的节点的内存地址大。请澄清。显然,因为下一个节点的地址比上一个节点的地址大不是严格的规则,所以在很小比例的情况下,新节点会得到更小的地址。