2016-07-04 2 views
2

Я смотрел на других форумах, как удалять каждый другой узел, но они всегда получают результат 1-> 3, а я хочу 2-> 4. У меня проблемы с этим. Я потратил часы, глядя на это, и любая помощь будет оценена по достоинству. Я добавил несколько операторов printf, чтобы увидеть, где я ошибаюсь. Это выход я получаю:Удалите каждый другой узел из связанного списка, заданного 1-> 2-> 3-> 4, чтобы получить 2-> 4?

17 3 8 8 20 13 15 17 10 13 


current: 17 
forward: 3 
free: 17 
current: 8 
forward->next: 8 
-------End------ 

free: 8 
current: 8 
forward->next: 20 
-------End------ 

free: 8 
current: 20 
forward->next: 13 
-------End------ 

free: 20 
current: 13 
forward->next: 15 
-------End------ 

free: 13 
current: 15 
forward->next: 17 
-------End------ 

free: 15 
current: 17 
forward->next: 10 
-------End------ 

free: 17 
current: 10 
forward->next: 13 
-------End------ 

free: 10 
current: 13 

Вот мой код:

node *deleteEveryOther(node *head) 
{ 
    node *forward, *current; 

    if (head == NULL) 
     return NULL; 

    current = head; 
    printf("\n\ncurrent: %d\n", current->data); 
    forward = head->next; 
    printf("forward: %d\n", forward->data); 

    while(current != NULL && forward != NULL) 
    { 
     printf("free: %d\n", current->data); 
     free(current); 

     current = forward->next; 
     printf("current: %d\n", current->data); 

     forward->next = current->next; 
     printf("forward->next: %d\n", forward->next->data); 
     //if(previous->next != NULL) 
      //previous = previous->next; 

     printf("-------End------\n\n"); 
    } 

    return head; 
} 

Здесь я редактировал (применяя алгоритм я видел) код немного:

узел * deleteEveryOther (узел * head) { узел * прежний, * текущий;

if (head == NULL) 
    return NULL; 

previous = head; 
current = head->next; 

free(previous); 
previous = current; 
current = head->next; 

while(current != NULL && previous != NULL) 
{ 
    previous->next = current->next; 

    free(current); 

    previous = previous->next; 

    if(previous != NULL) 
     current = previous->next; 

} 

return head; 

}

// ----------------- RECURSIVE ПОДХОД ----------------- ---------

void deleteEveryOtherRecursively(node *head)` 
{ 
    if (head == NULL) 
    return; 

    node *current = head; 

    if (current == NULL) 
     return; 

    node *forward = head->next; 
    head = current->next = forward->next; 

    free(current); 

    deleteEveryOtherRecursively(head); 
} 
+0

Что делать, если список имел 6 узлов? то что бы вы хотели, чтобы ваш список был «2-> 4' или« 2-> 6' – Cherubim

+0

Если бы у него было 6 узлов, например 1-> 2-> 3-> 4-> 5-> 6, то я бы хотел мой выход должен быть 2-> 4-> 6. – user6134432

+0

ОК, так что вы хотите, чтобы только четные узлы были правы :) @ user6134432 – Cherubim

ответ

2

Вы можете освободить первый узел и получить новую голову вне цикла while. Затем освободите все альтернативные узлы внутри цикла while.

Я немного изменил код.

struct node *deleteEveryOther(struct node *head) 
{ 
    struct node *forward, *current; 

    /* If empty list */ 
    if (head == NULL) 
      return NULL; 

    /* Free first element */ 
    current = head; 
    forward = head->next; 
    free(current); 

    /* Get new head */ 
    current = forward; 
    head = current; 

    /* Now remove all next elements */ 
    while (current != NULL) { 
      forward = current->next; 
      if (forward != NULL) { 
        current->next = forward->next; 
        free(forward); 
      } 
      current = current->next; 
    } 

    /* Return new head */ 
    return head; 
} 

В вашем коде имеется несколько ошибок. Например, вы не обновляете новый head, но возвращаете тот же старый head. Также вы разыменовали некоторые указатели, не проверяя, являются ли они NULL (в ваших заявлениях printf).

Это также можно сделать рекурсивно. В вашей версии вы не возвращаете голову (функция void), что является проблемой. Есть и другие проблемы. Вы можете сравнить код ниже с кодом и увидеть различия.

/* deleteEveryOtherRecursively: recursively delete odd numbered nodes */ 
struct node *deleteEveryOtherRecursively(struct node *head) 
{ 
    struct node *forward; 

    /* Base case */ 
    if (head == NULL) 
      return NULL; 

    forward = head->next; /* Get the next node in forward */ 
    free(head);   /* free old head */ 
    head = forward;  /* new head points to next elem */ 

    if (head != NULL)  /* recur down if needed */ 
      head->next = deleteEveryOtherRecursively(head->next); 

    return head;   /* return new head */ 
} 
+0

Я пытаюсь полностью понять код. Почему мы делаем head = текущую строку? – user6134432

+0

@ user6134432 Итак, мы обновляем 'head' связанного списка. 'head' указывает на первый узел в связанном списке. Мы возвращаем этот новый 'head' в последней строке как' return head; 'Теперь, поскольку мы удаляем все« нечетные »нумерованные узлы (например, узел 1, узел 3 и т. Д.), Так что теперь' head' должен указывать на узел 2 из исходного связанного списка (или NULL, если в исходном связанном списке было только 1 узел). И в то время, когда выполняется 'head = current;', 'current' указывает на 2-й узел в исходном связанном списке (или NULL, если в исходном связанном списке было только 1 узел). – sps

+0

Хорошо, что имеет смысл! Если бы мы решили сделать это рекурсивно, было бы намного проще просто интересно? Я попытаюсь сделать это рекурсивно, чтобы видеть. – user6134432

1

Возможно, вы захотите удалить первый узел, а затем применить алгоритм к оставшемуся связанному списку. Это один из способов, которым он должен работать, и это самый простой, на мой взгляд.

+0

Я думал об этом, так что просто освободите первый узел за пределами цикла while? – user6134432

+0

@ пользователь6134432 есть. –

+0

Я попробовал, но это действительно не работает. – user6134432

Смежные вопросы