Глубокая копия связанного списка

У меня есть двусвязный список, 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().

Обратите внимание, что вы также должны написать оператор присваивания в дополнение к конструктору копирования.

Другие вопросы по тегам