C 链表具有循环功能审查

C 链表具有循环功能审查,c,linked-list,C,Linked List,我写了一个代码来检查链表输入是否有一个循环,但是我的方法与互联网上的有点不同,它有效吗 /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ bool hasCycle(struct ListNode *head) { struct ListNode *p1,*p2; p1 = head;

我写了一个代码来检查链表输入是否有一个循环,但是我的方法与互联网上的有点不同,它有效吗

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode *p1,*p2;
    p1 = head;
    if(p1 == NULL) return 0;
    for(p1 = head;p1->next != NULL;p1 = p1->next){
        for(p2 = p1->next;p2 != NULL;p2=p2->next){
            if(p2 == p1) return 1;
            if (p2 == NULL) return 0;
        }
    }
    return 0;

}

你回来太早了:

    for(p2 = p1->next;p2 != NULL;p2=p2->next){
        if(p2 == p1) return 1;
        if (p2 == NULL) return 0;
    }
p2
变为空时,它只是意味着没有涉及
p1
的循环,而不是根本没有循环。通过在此处返回0,您仅检查头部节点的循环

去掉额外的返回值,这样在搜索完所有内容后才返回0

for(p1 = head;p1->next != NULL;p1 = p1->next){
    for(p2 = p1->next;p2 != NULL;p2=p2->next){
        if(p2 == p1) return 1;
    }
}
return 0;
编辑:

这仍然不起作用,因为如果循环不涉及第一个节点,它将进入无限循环。处理此问题的正确方法是对照找到的所有先前节点检查每个节点。这可以通过在访问节点时将节点放入列表来实现。如果在添加节点之前列表中已经存在该节点,则会发现一个循环


或者,您可以在初始化为0的每个节点中放置一个“已访问”标志。然后遍历列表,在运行时设置标志。如果该标志已设置,则您有一个循环。

您返回得太早了:

    for(p2 = p1->next;p2 != NULL;p2=p2->next){
        if(p2 == p1) return 1;
        if (p2 == NULL) return 0;
    }
p2
变为空时,它只是意味着没有涉及
p1
的循环,而不是根本没有循环。通过在此处返回0,您仅检查头部节点的循环

去掉额外的返回值,这样在搜索完所有内容后才返回0

for(p1 = head;p1->next != NULL;p1 = p1->next){
    for(p2 = p1->next;p2 != NULL;p2=p2->next){
        if(p2 == p1) return 1;
    }
}
return 0;
编辑:

这仍然不起作用,因为如果循环不涉及第一个节点,它将进入无限循环。处理此问题的正确方法是对照找到的所有先前节点检查每个节点。这可以通过在访问节点时将节点放入列表来实现。如果在添加节点之前列表中已经存在该节点,则会发现一个循环


或者,您可以在初始化为0的每个节点中放置一个“已访问”标志。然后遍历列表,在运行时设置标志。如果已经设置了该标志,则有一个循环。

能否举例说明操作代码失败的列表?例如,不存在涉及p1的循环,但在其他地方存在循环。除非我遗漏了一些明显的东西,否则这是不可能的。它毕竟是一个链表,而不是一般的DG。PS:AFAICT OP和您的代码在循环的情况下都绑定到一个无限循环,但这是一个不同的问题。正是我的意思-
NULL
永远不会被命中。无限循环,不是吗?@user58697如果我们只检查第一个节点,这将是一个问题,那么你是对的。要正确执行此操作,需要将当前节点与之前的所有节点进行检查。我要做个改变。你能举一个操作码失败的例子吗?例如,不存在涉及p1的循环,但在其他地方存在循环。除非我遗漏了一些明显的东西,否则这是不可能的。它毕竟是一个链表,而不是一般的DG。PS:AFAICT OP和您的代码在循环的情况下都绑定到一个无限循环,但这是一个不同的问题。正是我的意思-
NULL
永远不会被命中。无限循环,不是吗?@user58697如果我们只检查第一个节点,这将是一个问题,那么你是对的。要正确执行此操作,需要将当前节点与之前的所有节点进行检查。我会改变的。