#c #linked-list
#c #связанный список
Вопрос:
У меня есть код решения здесь:
// Pre-condition: The fronts of two linked lists are provided.
// Post-condition: A linked list is returned that is the result of
// interleaving the elements from each provided list.
// (e.g. {1, 2, 3} amp; { 4, 5, 6} would return {1, 4, 2, 5, 3, 6}
Node* interleave( Node*amp; front1, Node*amp; front2 ) {
if( !front1 ) return front2;
if( !front2 ) return front1;
Node* third = front1->next; //this will become the third element
Node* fourth = front2->next; // this will be come the fourth element
front1->next = front2;
front2->next = third;
third = interleave(third, fourth);
return front1;
}
Я вроде как понимаю это, но я бы никогда не смог придумать что-то подобное, поскольку я очень плох в рекурсии. Есть ли другой способ решить эту проблему нерекурсивно? если да, не могли бы вы дать мне подсказку? Я пробовал это:
Node* interleave( Node*amp; front1, Node*amp; front2 ) {
Node* newNode = new Node;
while(front1!=NULL amp;amp; front2!=NULL){
newNode = front1->next;
newNode = front2->next;
front1 = front1->next;
front2 = front2->next;
}
return newNode;
}
Я уверен, что это неправильно, но это единственное, что я могу придумать прямо сейчас. Пожалуйста, помогите. Спасибо
Комментарии:
1. Это похоже на вопрос домашнего задания.
Ответ №1:
Попробуйте нарисовать два связанных списка параллельно на листе бумаги. Поместите несколько чисел в узлы, просто чтобы отличить их друг от друга. Подумайте, как бы вы повторно соединили их, чтобы сформировать единый список, начиная с заголовка (или «начала») и продвигаясь вниз. Обратите внимание, что вам нужно отслеживать несколько специальных узлов, таких как первый узел результирующего списка и несколько других. Шаблон должен стать понятным.
(Обратите внимание, что нет необходимости создавать новый узел с new
.)
Комментарии:
1. Узел* newNode = новый узел; вы правы. Я только что узнал об этом несколько дней назад, не следовало использовать новую конструкцию. Спасибо.
Ответ №2:
В вашем коде есть несколько ошибок:
Node* interleave( Node*amp; front1, Node*amp; front2 )
Я не вижу необходимости в ссылке на указатель, поскольку первый элемент в front1 будет оставаться первым, и вам вообще не нужно связываться с front2.
Node* newNode = new Node;
while(front1!=NULL amp;amp; front2!=NULL){
newNode = front1->next;
Это вызывает утечку памяти — вы выделяете по крайней мере байты sizeof (узла), но затем вы теряете ссылку на указатель, и вы больше не сможете его удалить.
Кроме того, вы ничего не делаете с newNode, поэтому вы также можете выбросить его.
front1 = front1->next;
front2 = front2->next;
По сути, вы говорите, что front1 скорее будет указывать на следующий элемент, и поскольку вы передали ссылку на front1, вы изменяете реальный указатель. В конечном итоге front1 или front2 будут равны НУЛЮ, и цикл завершится, так что по крайней мере один из двух заданных параметров станет бесполезным. Далее вы ничего не меняете, поэтому порядок останется неизменным — вы просто проходите по спискам.
Одним из подходов могло бы быть присвоение значению front2 значения front1-> next, затем замена указателей и повторение снова:
Node *a = front1, *b = front2;
while (a amp;amp; b) {
Node* tmp = a->next;
a->next = b;
b = tmp;
a = a->next;
}
return front1;
Я не тестировал это, но это должно быть близко к работе. Вы можете заменить подробный код подкачки на std::swap(), если вы используете stl.
Идея проста: предположим, у вас есть два списка:
A -> B -> C -> NULL
D -> E -> F -> NULL
вы говорите, что следующий элемент A будет первым элементом во втором списке, поэтому D:
A -> D -> E -> F -> NULL
и тогда второй список становится преемником древнего A, так что просто B -> C -> NULL. Затем вы продвигаете a, чтобы указать на его новый следующий, или D, так что теперь у вас есть:
D -> E -> F -> NULL
B -> C -> NULL
и вы повторяете:
D -> B -> C -> NULL
E -> F -> NULL
B -> C -> NULL
F -> NULL
и так далее, пока не будет выполнено значение NULL. Тогда front1, который все еще указывает на A, должен иметь правильную последовательность (то есть, если я не ужасно ошибаюсь : p )
Комментарии:
1. Я только что видел ответ бета-версии: я согласен, вы должны попытаться нарисовать два списка — это то, что я сделал в любом случае!