Почему я теряю узел при перетасовке связанного списка?

Я работаю над проектом. Часть проекта нуждается в перетасованном связном списке. Эта функция является реализацией алгоритма перетасовки Фишера-Ятса. Он помещает связанный список в массив. Потом перемешивает. Затем повторно связывает его.

После некоторого тестирования я обнаружил, что иногда, когда я перетасовываю связанный список, я где-то теряю узел. Я провел несколько тестов с убсаном и асаном. Оба они ничего не показывают. Раньше у меня была проблема с этой функцией, которая позже вызывала segfault. Ошибка сегментации была вызвана неправильным повторным связыванием связанного списка. В частности, последний узел перед перетасовкой в ​​связанном списке не был повторно привязан правильно. Я немного исправил это, сделав список круговым, прежде чем перетасовать его.

Вот код, используемый для перетасовки вместе с функциями подкачки и повторного связывания:

      linked_node* shuffle(linked_node* head) {
    int count = 0;
    linked_node* count_head = head;
    while (count_head != NULL) {
        count++;
        count_head = count_head->next;
    }

    #ifdef DEBUG 
        fprintf(stderr, "count: %i\r\n", count);
    #endif

    linked_node** array = malloc(count * sizeof(linked_node*));

    int i = 0;

    linked_node* add_head = head;

    for (i = 0; i < count; i++) {
        array[i] = add_head;
        add_head = add_head->next;
    }
    
    //made circluar to prevent segfault with the last node
    array[count - 1]->next = head;

    srand48(time(NULL));



    for (int j = count - 1; j > 0; j--) {
        int random = lrand48() % (j+1);

        array_swap(&array[j], &array[random]);
    }

    for (int k = 0; k > count - 1; k++) {
        relink(array[k], array[k + 1]);
    }

    linked_node* new_head = array[0];

    //made circular for ease of use later
    array[count - 1]->next = new_head;

    free(array);

    return new_head;
}

static inline void relink(linked_node* prev, linked_node* next) {
    if (prev != NULL && next != NULL) {
        prev->next = next;
    }
}

void array_swap(linked_node** a, linked_node** b) {
    linked_node* temp = *a;
    *a = *b;
    *b = temp;
}

1 ответ

Решение

В этом цикле for есть опечатка

      for (int k = 0; k > count - 1; k++) {
                ^^^^^^^^^^^^^
    relink(array[k], array[k + 1]);
}

Кажется, ты имеешь в виду

      for (int k = 0; k < count - 1; k++) {
                ^^^^^^^^^^^^^
    relink(array[k], array[k + 1]);
}

Также это заявление

      //made circluar to prevent segfault with the last node
array[count - 1]->next = head;

является избыточным и фактически не действует. Убери это.

Это утверждение

      //made circular for ease of use later
array[count - 1]->next = new_head;

можно заменить это утверждение

      array[count - 1]->next = NULL;
Другие вопросы по тегам