Рекурсивно распечатать односвязный список в C

Я должен рекурсивно работать с круговым односвязным списком в C, моя проблема в том, что я рекурсивен, я не могу правильно распечатать список, и у меня есть некоторые проблемы с доступом к ключу tmp-> в функции display () (сегментация ошибка из-за незаконного доступа), когда я нажимаю более 1 элемента и хочу отобразить список позже. И tmp, и list объявлены как struct node* tmp = NULL; и struct node* list = NULL; Основной экстракт:

    case 8:
tmp = list;
        if (tmp->next == tmp)
    printf("\n%d\n", tmp->key);
else
            display (list, tmp);
        break;

Функция:

void display (struct node* head, struct node* tmp){

    if (head != NULL){
        if (tmp != head){
            printf ("%d ", tmp->key);
            tmp = tmp->next;
            display(head, tmp);
        }
    }
}

person ak27    schedule 07.04.2020    source источник
comment
вы управляете только круговым списком, имеющим одну ячейку?   -  person bruno    schedule 07.04.2020
comment
@бруно Что ты имеешь в виду? если вы имеете в виду только одно поле (ключ), то да, требуется только одно поле.   -  person ak27    schedule 07.04.2020
comment
нет, я спрашиваю, потому что я вижу только случай, когда list-›next == list / tmp-›next == tmp, поэтому циклический список с одной ячейкой не обнаруживать круговой список из двух ячеек, где список-›следующий != список, но список-›следующий-›следующий == список и т. д.   -  person bruno    schedule 07.04.2020


Ответы (2)


Дизайн предполагает, что tmp должен указывать на существующий узел в списке.

Если tmp равно NULL, вам придется проверить это условие в display(), чтобы избежать ошибки сегментации.

Вы также захотите проверить, является ли tmp NULL перед этим кодом:

        if (tmp->next == tmp)
person rtx13    schedule 07.04.2020
comment
Мне не нужно проверять, является ли tmp значением NULL, потому что я назначаю начало списка tmp перед вызовом display. Можете указать, где я должен редактировать свой код, пожалуйста? потому что я действительно не понимаю - person ak27; 07.04.2020
comment
Отправьте как можно больше кода, чтобы позволить другому пользователю SO скомпилировать тест. Вы упомянули выше, что «я назначаю начало списка tmp перед вызовом display», но в вашем вопросе говорится только «struct node* tmp = NULL» и «struct node* list = NULL». Это означает, что и tmp, и список равны NULL. Чем больше подробностей вы предоставите, тем лучше я или кто-то другой буду готов ответить. - person rtx13; 08.04.2020

void display (struct node *head, struct node *this){

    if (!head) return;
    if (!this) return;

    printf ("%d ", this->key);

    if (this->next == head) return;
    display(head, this->next);
}

А хвостовая рекурсия убирается компилятором (gcc -O4 -S):


.globl  display
        .type   display, @function
display:
.LFB24:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rdi, %rbp
        pushq   %rbx
        .cfi_def_cfa_offset 24
        .cfi_offset 3, -24
        subq    $8, %rsp
        .cfi_def_cfa_offset 32
        testq   %rdi, %rdi
        je      .L1
        testq   %rsi, %rsi
        movq    %rsi, %rbx
        jne     .L4
        jmp     .L1
        .p2align 4,,10
        .p2align 3
.L12:
        testq   %rbx, %rbx
        je      .L1
.L4:
        movl    8(%rbx), %edx
        xorl    %eax, %eax
        movl    $.LC0, %esi
        movl    $1, %edi
        call    __printf_chk
        movq    (%rbx), %rbx
        cmpq    %rbp, %rbx
        jne     .L12
.L1:
        addq    $8, %rsp
        .cfi_def_cfa_offset 24
        popq    %rbx
        .cfi_def_cfa_offset 16
        popq    %rbp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
.LFE24:
        .size   display, .-display
person wildplasser    schedule 07.04.2020