2013-08-23 3 views
3

Я пытаюсь научиться C, и, как и многие люди, я немного застрял в указателях. В любом случае, я сделал рекурсивную функцию, которая разрушает мой связанный список, но, как я отлаживал, когда я вернулся из функции, глава списка не является нулевым, как и должно быть, поэтому я предполагаю, что это является одним из основных недоразумений с указатели. Вот функция:C Linked-list Destroy Function

void destroy(struct node* n){ 
    if(!n) return; 
    destroy(n->next); 
    free(n); 
    n = NULL; } 

Заранее спасибо.

+4

«n» - это локальная переменная, поэтому «n = NULL» имеет только локальный эффект, что означает, что он не имеет никакого эффекта, так как он находится в конце функции. – ruakh

+0

Просьба показать код, который показывает, что голова не равна нулю. –

+0

Расширяясь от того, что сказал @ruakh, если вы хотите изменить указатель, вы должны передать указатель на этот указатель (т. Е. 'Struct node **'), точно так же, как вам нужно было бы передать указатель, если вы хотите изменить что-нибудь еще. –

ответ

1

Вы должны использовать указатель, указывающий на ваш список, вызов с destroy(&n):

/* clear complete list */ 
void destroy(struct node **n) 
{ 
    if (*n== NULL) 
     return; 

    if ((*n)->next == NULL) 
    { 
     free(*n); 
     *n= NULL; 
    } 
    else 
    { 
     struct node *iter = *n; 
     struct node *prev = NULL; 

     /* get last item and previous one */ 
     while (iter->next != NULL) 
     { 
      prev = iter; 
      iter = iter->next; 
     } 

     prev->next = NULL; 
     free(iter); 

     /* repeat call */ 
     clear(n); 
    } 
} 

Надеется, что это может помочь вам.

Как я вижу решение spt025, у меня похоже, что у меня слишком много кода. Я тоже новичок;)

+0

Ваш вызов 'clear()' неясен; вы хотели еще раз называть 'destroy()'? Ваш цикл, чтобы найти конец, прежде чем выпустить что-то, а затем снова вызвать функцию рекурсивно (с простой рекурсией хвоста), кажется немного странным ;. Я думаю, что это сработает (я его не тестировал), но исходный код с рекурсией и без цикла проще - хотя он может занять более глубоко, чем ваш код. –

+0

О, мое плохое. Действительно, это должно быть 'destroy()'. И да, моя функция слишком крута, и я рассмотрю другие решения, размещенные здесь, чтобы улучшить мою. Тем не менее, он работает;) – pzaenger

2

Голова была освобождена, когда эти функции заканчиваются, но она не равна нулю. Все в C передается по значению. Итак, вы передаете копию местоположения головы в уничтожение. Эта память освобождается, но голова не изменяется.

Вы могли бы написать это как:

destroy(&head); 

void destroy(struct node** n){ 
    if(!*n) return; 
    destroy(&((*n)->next)); 
    free(*n); 
    *n = NULL; 
} 
6
void deleteList(struct node** head_ref) 
{ 
    struct node* current = *head_ref; 
    struct node* next; 
    while (current != NULL) { 
    next = current->next; 
    free(current); 
    current = next; 
    } 
    *head_ref = NULL; 
} 

Попробуйте, как это .... вы можете изменить имена, как вы хотите. Если вам все еще нужна помощь, дайте мне знать.

+0

+1 для того, чтобы не использовать рекурсии (и, таким образом, избежать переполнения стека, что является неизбежным следствием, если размер становится достаточно большим). –

+0

спасибо человеку ... :) – spt025

+0

@ Маты: он [плагиат] (http://meta.stackexchange.com/questions/160077/ive-been-accused-of-plagiarism-what-do-i-do) это от http://breakinterview.com/write-a-function-to-delete-a-linked-list/ Дополнительные доказательства, он даже не пытался * объяснить * проблему и решение в собственном техническом плане. Этот ответ, очевидно, просто свалка кода, которую он, к счастью, нашел в Google, и сомневающийся «попробуй это ...». – BalusC