#c #linked-list #copy-constructor
#c #связанный список #copy-constructor
Вопрос:
Это домашнее задание
Я работаю над реализацией класса связанного списка для моего класса C , и конструктор копирования меня очень смущает.
Связанный список состоит из структур, называемых элементами:
struct Elem
{
int pri;
data info;
Elem * next;
};
Elem * head;
info — это отдельный пользовательский класс, который хранится в Elem.
подпись для конструктора копирования:
linkedList::linkedList( const linkedList amp;v )
Проблема, с которой я сталкиваюсь, в основном заключается в том, что я использую свою логику и фактически записываю ее как код.
Моя общая идея заключается в:
- Установите head в v.head (head = v.head)
- Установите значения элемента в v (pri = v.pri , info = v.info , следующий = v.следующий)
- Выполните итерацию, повторяя шаг 2.
Это общая идея?
Любая помощь была бы отличной. Помните, что это домашнее задание, поэтому, пожалуйста, никаких прямых ответов!
Спасибо за ваше время
====================================================================================================================================================================
Всем спасибо за ваше время!
Я думаю, что я это понял:
//Copy Constructor
LinkedList::LinkedList( const LinkedList amp;v )
{
Elem * p1 = 0;//current
Elem * p2 = 0;//next
if( v.head == 0 )
head = 0;
else
{
head = new Elem;
head -> pri = v.head -> pri;
head -> info = v.head -> info;
p1 = head;
p2 = v.head -> next;
}
while( p2 )
{
p1 -> next = new Elem;
p1 = p1 -> next;
p1 -> pri = p2 -> pri;
p1 -> info = p2 -> info;
p2 = p2 -> next;
}
p1 -> next = 0;
}
Я почти уверен, что это работает. Я нарисовал несколько логических картинок, чтобы помочь, и у меня не возникло никаких проблем.
Комментарии:
1. Что именно должен делать конструктор копирования? Создание копии каждого узла с соответствующими ссылками звучит разумно, но это не единственная возможность.
2. 1 За прямое указание домашнего задания и отсутствие прямых ответов .
3. Спасибо, что дали мне правильный совет! Я реализовал конструктор глубокого копирования для своих узлов, чтобы иметь возможность возвращать объект «конечного» узла со структурой ссылок для родительского узла и его родительского узла … чтобы оставаться в такте. Использовал его для алгоритмов поиска по дереву
Ответ №1:
Вы должны быть осторожны с шагом 1 и частью шага 2. Шаг 1 должен выделить новый узел и использовать его как head
. На шаге 2 часть о next = v.next
том, что, если вы не собираетесь делать поверхностную копию, неверна.
Когда вы копируете контейнер, такой как связанный список, вам, вероятно, требуется глубокое копирование, поэтому необходимо создавать новые узлы и копировать только данные. Указатели next
и prior
в узлах нового списка должны ссылаться на новые узлы, которые вы создаете специально для этого списка, а не на узлы из исходного списка. Эти новые узлы будут иметь копии соответствующих данных из исходного списка, так что новый список можно считать по значению или глубокой копией.
Вот картинка, изображающая различия между мелким и глубоким копированием:
Обратите внимание, что в части глубокого копирования диаграммы ни один из узлов не указывает на узлы в старом списке. Для получения дополнительной информации о разнице между мелкими и глубокими копиями см. Статью Википедии о копировании объектов.
Комментарии:
1. О! Картинки! Это определенно поможет прояснить ситуацию. 1
Ответ №2:
-
Вы не должны устанавливать
this->head = v.head
. Потому что head — это просто указатель. Что вам нужно сделать, это создать новый заголовок и скопировать значения по отдельности изv.head
вашего нового заголовка. В противном случае у вас было бы два указателя, указывающих на одно и то же. -
Затем вам нужно будет создать временный
Elem
указатель, который начинается сv.head
и перебирает список, копируя его значения в новыеElem
указатели в новую копию. -
Смотрите выше.
Комментарии:
1. Примечание: Когда вы копируете его значения, не копируйте его указатель. В общем, никогда не копируйте указатель в конструкторе копирования. Скопируйте объект, на который указывается.
Ответ №3:
Что должен копировать ваш конструктор копирования? Это должно pri
быть легко скопировать. Он info
также должен легко копировать. И если next
значение не равно null, оно также должно скопировать его. Как вы можете копировать next
? Подумайте о рекурсивном: ну, next
это Elem *
, и Elem
имеет конструктор копирования: просто используйте его, чтобы скопировать ссылку Elem
и ссылаться на нее.
Вы также можете решить эту проблему итеративно, но рекурсивное решение гораздо более интуитивно понятно.
Комментарии:
1. Правда, это довольно просто, если у Elem есть конструктор копирования
2. Мы намеренно пока не выполняем рекурсию, чтобы нам было легче увидеть, что происходит. Он показал нам рекурсивный способ и намеренно сказал, что мы потерпим неудачу, если сделаем это таким образом. O_O
3. @Joshua: Вы должны упомянуть такие ограничения.
Ответ №4:
Итак, вот мой ответ (не знаю, соответствует ли это вашему домашнему заданию или нет — у преподавателей, как правило, иногда есть свои собственные идеи;):
Как правило, конструктор копирования должен «копировать» ваш объект. Т.е. Скажем, у вас есть LinkedList l1 и выполните LinkedList l2 = l1 (который вызывает LinkedList::LinkedList(l1)), тогда l1 и l2 являются полностью отдельными объектами в том смысле, что модификация l1 не влияет на l2 и наоборотнаоборот.
Когда вы просто назначаете указатели, вы не получите реальную копию, поскольку разыменование и изменение любого из них повлияют на оба объекта.
Вы скорее хотите сделать реальную глубокую копию каждого элемента в вашем исходном списке (или сделать копию только по требованию, если вы хотите быть фантазией).
Ответ №5:
Вы забыли строку return;
после
if( v.head == 0 )
head = 0;
Вам нужно выйти, верно?