Глубокая копия связанного списка
У меня есть двусвязный список, m_Terminal1 - начало списка, а m_Terminal2 - конец списка. Вот мой код
CBusLine(const CBusLine & orig){
m_Terminal1 = new TStop(orig.m_Terminal1 -> m_Name);
m_Terminal2 = new TStop(orig.m_Terminal1 -> m_Name);
TStop * tmpx = m_Terminal2;
TStop * copy = orig.m_Terminal1;
copy = copy ->m_Next;
while(copy != NULL){
TStop * copy_tmp = new TStop(copy->m_Name);
tmpx -> m_Next = copy_tmp;
copy_tmp -> m_Prev = tmpx;
tmpx = copy_tmp;
copy = copy->m_Next;
}
К сожалению, это не работает, когда я хочу распечатать список, есть только первый пункт. Вот исходный файл http://pastebin.com/YCKyZ31K. Может ли кто-нибудь помочь мне? заранее спасибо
2 ответа
Вы создаете два объекта с тем же именем, что и первая остановка (m_Terminal1
а также m_Terminal2
) и добавление списка остановок в m_Terminal2
, Потому что переменные указывают на разные места в памяти (любезно new
звонки), они не то же самое, и, в конце концов, m_Terminal2
будет иметь полный список, а m_Terminal1
будет просто первая остановка. Во время этого процесса вы не сохраняете последнюю остановку в m_Terminal2
,
Один из способов исправить это - инициализировать и сохранить только первую остановку, пройти и добавить все остановки и сохранить (НЕ повторно инициализировать) последнюю остановку.
CBusLine(CBusLine & orig){
m_Terminal1 = new TStop(orig.m_Terminal1 -> m_Name);
TStop * tmpx = m_Terminal1;
TStop * copy = orig.m_Terminal1;
copy = copy ->m_Next;
while(copy != NULL){
TStop * copy_tmp = new TStop(copy->m_Name);
tmpx -> m_Next = copy_tmp;
copy_tmp -> m_Prev = tmpx;
tmpx = copy_tmp;
copy = copy->m_Next;
m_Terminal2 = tmpx;
}
Вы должны повторно использовать уже написанный код. Вы написали Add()
функция, так почему бы не использовать его?
Во-первых, исправьте функцию Add(), чтобы она вызывала другую функцию, единственной целью которой является добавление узла в конец последовательности:
void CBusLine::Add(istream& is)
{
string line;
while(is.good())
{
getline(is, line);
if(line == "")
continue;
AddInternal(line);
}
}
void CBusLine::AddInternal(string& line)
{
TStop * n = new TStop(line);
if(m_Terminal2 == NULL){
m_Terminal1 = n;
m_Terminal2 = n;
}
else{
m_Terminal2 -> m_Next = n;
n -> m_Prev = m_Terminal2;
m_Terminal2 = n;
}
}
Причина разрушения функции Add() состоит в том, что теперь конструктор копирования (и оператор присваивания) стал очень простым для написания.
CBusLine(const CBusLine & orig)
{
TStop *startTerm = orig.m_Terminal1;
while ( startTerm != orig.m_Terminal2 )
{
AddInternal( startTerm->m_name);
startTerm = startTerm->m_Next;
}
}
Конечно, AddInternal должен работать правильно. Я предполагаю, что m_Terminal1 и m_Terminal2 являются началом и концом связанного списка.
Учитывая, что AddInternal() работает правильно, конструктор копирования представляет собой простой цикл, идущий от начала до конца терминала и вызывающий AddInternal() со строковыми данными терминала. Это намного проще и логичнее, чем воссоздание кода, который вы уже написали в функции Add().
Обратите внимание, что вы также должны написать оператор присваивания в дополнение к конструктору копирования.