p=head;
q=head->next;
while(p!=NULL && q!=NULL)
{
if(p==q) { //Loop detected! exit(0); }
p=p->next;
q=(q->next)?(q->next->next):q->next; --how this line works ??
}
答案 0 :(得分:1)
首先,如果列表中没有循环,则条件p==q
将永远不会成立,因为q
始终位于p
的“前方”。
然后,p
和q
之间的距离在每次迭代时增加1。因此,如果存在循环,则只要距离是循环长度的整数倍,条件p==q
就为真。
有问题的行将q
提前2个位置。它首先检查q
在向前移动一个位置后是否不会到达列表末尾,以避免空指针解除引用。 (q->next
位于q
之前一个位置,q->next->next
位于前方两个位置。)
答案 1 :(得分:0)
引用:
Q =(Q->下面)(Q->下一步 - >接着):Q->接下来; - 这条线有效吗?
这也可以是:
if(q->next) {
q = q->next->next;
} else {
q = q->next;
}
答案 2 :(得分:0)
如果你在链表中有一个循环,你可以通过在列表中运行两个指针找到它,一个通过列表前进一个元素,另一个通过两个元素。
如果没有循环,那么“更快”的循环将始终位于较慢的循环之前。如果有一个循环,它们最终将指向相同的元素,因为它们以不同的速度通过循环。
所有这一行
q=(q->next)?(q->next->next):q->next;
确实将更快的指针推进两个,如果可以的话,。如果它不能,因为它接近这个列表的末尾,它只是前进一个。
在英语中,如果此元素不是最后一个,则将新指针设置为超出下一个的指针(可能为NULL)。如果此元素 是最后一个,请将其设置为下一个,将为NULL。
我自己,我会把它写成:
q=(q->next)?(q->next->next):NULL;
但这只是风格问题。
答案 3 :(得分:0)
p
总是在每次迭代中向前移动一步,但q
向前移动两步(除非列表结束;因此检查是否存在q->next
)。这意味着在每次迭代q
都比p
更远。如果列表中没有循环,q
将只是到达列表的末尾,循环将终止。如果是一个循环,那么q
最终会循环遍历它(通过更快地前进)并“追赶”到p
,即p == q
将是真。
(如果你另外询问特定行的含义是什么,那么这只是一个较短的说法:
if (q-next) {
q = q->next->next; // Go forward two steps if possible
} else {
q = q->next; // Go forward one step otherwise
}
)
答案 4 :(得分:0)
这行代码:
q=(q->next)?(q->next->next):q->next;
可能会更改为:
q=(q->next)?(q->next->next):NULL;
所以这只是检查列表是否结束。如果是 - 比没有循环。