简体   繁体   中英

Deep copy of linked list

I have doubly linked list, m_Terminal1 is the begin of list, and m_Terminal2 is the end of the list. Here is my code

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;
      }

Unfortunately, it doesn't work, when I want to print out the list, there is only first item. Here is source file http://pastebin.com/YCKyZ31K . Could somebody help me? Thank you in advance

You're creating two objects that have the same name as the first stop ( m_Terminal1 and m_Terminal2 ) and adding the list of the stops to m_Terminal2 . Because the variables point to different places in memory (courtesy of the new calls), they aren't the same item, and in the end, m_Terminal2 will have the full list, while m_Terminal1 will just have the first stop. During this process, you aren't storing the last stop in m_Terminal2 .

One way to fix this is to only initialize and store the first stop initially, go through and add all of the stops, and store (NOT re-initialize) the last stop.

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;
}

You should reuse code already written. You wrote an Add() function, so why not use it?

First, fix the Add() function so that it calls another function where the sole purpose is to add a node at the end of the sequence:

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;
    }
}

The reason for breaking up the Add() function is that now, the copy constructor (and assignment operator) become very simple to write.

CBusLine(const CBusLine & orig)
{
    TStop *startTerm = orig.m_Terminal1;
    while ( startTerm != orig.m_Terminal2 )
    {
       AddInternal( startTerm->m_name);
       startTerm = startTerm->m_Next;
    }
}

Of course, the AddInternal has to work correctly. I'm assuming that m_Terminal1 and m_Terminal2 are the start and end of the linked list.

Given that AddInternal() works correctly, the copy constructor is a simple loop, going from start to end terminal, and calling AddInternal() with the terminal's string data. This is much more simpler and makes more sense logically than recreating code you already wrote in the Add() function.

Note that you must also write an assignment operator in addition to the copy constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM