2015-01-30 1 views
0

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

void f_insert_by_value(the_individual **head, char *str, int a) { 
    the_individual *current = *head, *temp = f_create(str, a); 

    if (*head == NULL) *head = temp; 
    else { 
     if (temp->age < (*head)->age) { 
      temp->next = (*head); 
      (*head)->prev = temp; 
      (*head) = (*head)->prev; 
     } 
     else { 
      while (temp->age > current->age && current->next != NULL) current = current->next; 
      if (current->next = NULL) { 
       temp->prev = current; 
       current->next = temp;    
       current = current->next; 
      } 
      else { 
       temp->prev = current->prev; 
       temp->next = current; 
       current->prev->next = temp; 
       current->prev = temp; 
      } 
     } 
    } 
    return; 
} 

вина Сегментация происходит по линии "current-> prev-> следующая = Темп". Я попытался напечатать адреса, чтобы понять, почему это происходит, и выяснил, что узел, который является первым на входе, всегда заканчивается тем, что его предыдущий элемент указывает на NULL. Может ли кто-нибудь объяснить, почему это происходит и как его можно исправить? Спасибо.

+0

Чтобы избежать всех этих пограничных случаев (во-первых, prev = NULL) и т. Д., Многие люди реализуют эти списки, такие как статические фиктивный элемент, который подключен к краям списка. Затем вы не запрашиваете NULL, но если ваш указатель является адресом манекена, чтобы узнать, что вы находитесь спереди или сзади вашего списка. Когда вы вставляете новые узлы, этот небольшой трюк позволяет вам тестировать NULL-указатели повсюду. – BitTickler

+0

@ пользователь2225104 имеет хороший совет. Хакерные обходные пути, подобные этому, делают C fun –

ответ

2

На первом узле current-> prev имеет значение null, поскольку ток является первым, вы получили его правильно.

temp->prev = current->prev; 
temp->next = current; 

Эта вещь является правильной, вы устанавливаете новый узел в нужном месте, но теперь current не приводят к правильной вещи. You схемы это один на данный момент:

NULL <= temp => current 
NULL <= current <=> ... 

И вы хотите

NULL <= temp <=> current <=> ... 

Так что единственное, чего не хватает, что предыдущий элемент current является temp. Так что я думаю, что просто удаление линии

current->prev->next = temp 

должны сделать трюк для первой вставки элемента, так как вы настроили current->prev сразу после.

Так что я предполагаю, что ваше состояние блок должен быть таким:

temp->prev = current->prev; 
temp->next = current; 
if (current->prev != NULL) { 
    current->prev->next = temp; 
} 
current->prev = temp; 

Как сказано в комментариях, если вы хотите, чтобы избежать нулевой проблемы указателя с связанного списка, вы можете добавить манекен в начале и в самом конце вашего списка, которые являются контроллерами, говорящими, что вы достигаете предела. Вы можете найти дополнительную информацию об этих типах связанных списков (с узлом Sentinel) here

+0

Да, хотя статья в википедии немного глупо в отношении того факта, что они фактически распределяют узел-дозор. Это пустая трата. Вы просто делаете 1 статический для всех списков одного и того же типа в модуле реализации списка, и не имеет значения, что он подключен к 10000 экземплярам списков. Почему так? Потому что вы никогда не используете sentinel-> next и т. Д. Вы только установите его для удобства вашего вставляемого кода. – BitTickler

+0

@Dimitri, но скажем, если у меня есть element1, element2, temp и current указывают на element2. Я хочу вставить temp между этими двумя элементами. temp-> prev = current-> prev, temp-> next = current, current-> prev = temp, но теперь element1-> next по-прежнему указывает на element2 not temp, поэтому я думаю, что current-> prev-> next = temp необходимо, потому что он делает element1-> следующую точку в temp? – Evil0Teddy

+0

О, ты совершенно прав. Я только думал о процессе для первого элемента. Для других элементов вы хотите сохранить эту строку. Я отредактирую свой ответ –

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