Что означает оператор AND применительно к указателям в связанном списке? - PullRequest
1 голос
/ 22 июня 2019

Я пытаюсь понять код C, написанный для обнаружения и удаления цикла в связанном списке (взято из здесь ).Хотя все остальное имеет для меня смысл, я не могу понять, что происходит внутри оператора while.В частности, как логическое И ведет себя при применении к структурам указателей?

while (slow_p && fast_p && fast_p->next) 

Здесь использовался подход «заяц и черепаха», в котором мы используем два указателя, один быстрый и один медленный,

/* Link list node */
struct Node 
{ 
    int data; 
    struct Node* next; 
}; 

/* Function to remove loop. Used by detectAndRemoveLoop() */
void removeLoop(struct Node *, struct Node *); 

/* This function detects and removes loop in the list 
  If loop was there in the list then it returns 1, 
  otherwise returns 0 */

int detectAndRemoveLoop(struct Node *list) 
{ 
    struct Node  *slow_p = list, *fast_p = list;

while (slow_p && fast_p && fast_p->next) 
{ 
    slow_p = slow_p->next; 
    fast_p  = fast_p->next->next; 

    /* If slow_p and fast_p meet at some point then there 
       is a loop */
    if (slow_p == fast_p) 
    { 
        removeLoop(slow_p, list); 

        /* Return 1 to indicate that loop is found */
        return 1; 
    } 
} 

/* Return 0 to indeciate that ther is no loop*/
return 0; 

}

1 Ответ

4 голосов
/ 22 июня 2019

Имеется условие, обеспечивающее разрывы и выходы цикла, если любой из трех указателей равен NULL.Пустой указатель всегда оценивается как логическое значение false в C. См. https://en.wikipedia.org/wiki/Null_pointer#Null_pointer.

При текущей логике, вероятно, что ни один из указателей не будет равен NULL, если в вашем списке существует циклпотому что мы обнаруживаем петлю и вырываемся из нее.Указатель fast_p может быть NULL только в том случае, если в вашем списке нет цикла, и вы только что закончили обход всего списка в попытке найти его.

enter image description here

Последовательность выполнения происходит следующим образом

  1. slow_p будет на узле 2, а fast_p будетбыть в узле 3
  2. slow_p будет в узле 3, а fast_p будет в узле 5
  3. slow_p будет в узле 4 и fast_p прошел бы мимоциклический узел и снова будет в узле 3
  4. slow_p будет в узле 5 и fast_p будет в узле 5

В этот момент оба эти указателя указывают наузел с тем же адресом, так что сравнение адресов будет утверждать, вызывая разрыв функции и возвращая адрес slow_p, который теперь точно указывает на узел, вызывающий этот циклический цикл.

...