Laurel Link
Laurel Link

Reputation: 305

How do I implement a deep copy constructor into a linked list?

For this problem that I'm currently working on, I'm trying to create a method within this linked list that performs a deep copy from one item to another. Right now the inside of the method is empty because I cannot get anything to work for the life of me. Is there any way I could get some help implementing this deep copy constructor in the area of code below that is commented? Thanks.

#include <string>
#include <iostream>
#include <cstddef>

using std::string;

class Item { 

public:

  string s; 

  Item(const char *a_s = "") { 
    s = a_s;
  }

  Item(string a_s) {
    s = a_s;
  }
};


class List {

  private:

      class ListNode { 

        public: 
          Item item; 
          ListNode * next; 
          ListNode(Item i) { 
            item = i;
            next = nullptr;
          }
      }; 

      ListNode * head; 
      ListNode * tail;

  public:

      class iterator {

        ListNode *node;

      public:
        iterator(ListNode *n = nullptr) {
          node = n;
        }

        Item& getItem() { return node->item; } //Not sure how this works
        void next() { node = node->next; }
        bool end() { return node==nullptr; }

      };



  public:

      List() {
        head = nullptr;
        tail = nullptr; //Sets the head and tail
      }

      List(const List & copy) { //Trying to create a copy constructor right here.

      }

      bool empty() { //Tells you if the list is empty
        return head==nullptr;
      }

      void append(Item a) { 

        ListNode *node = new ListNode(a);
          if ( head == nullptr ) {
            head = node;
            tail = node;
          } else {
            tail->next = node;
            tail = node;
          }
      }

      bool remove (Item &copy);

      void traverse() {
        ListNode *tmp = head;
        while(tmp != nullptr) {
          tmp = tmp->next;
        }
      }

      iterator begin() const {
        return iterator(head);
      }

};

    bool List::remove(Item &copy)
    {
      if (!empty()) {
        copy = head->item;
        ListNode *tmp = head->next;
        delete head;
        head = tmp;
        if (head==nullptr)
          tail = nullptr;
        return true;
      }
      return false;
    }


int main() {
   List l;
   l.append("eggs");

   List l2 = l; 

   std::cout << "done.\n";

   return 0;
}

Upvotes: 0

Views: 562

Answers (1)

PaulMcKenzie
PaulMcKenzie

Reputation: 35454

Assuming that append() is working correctly, you can just call it repeatedly in a loop for each item in copy.

This approach, given how you implemented your linked list with a tail pointer, makes it an ideal solution. You wrote the append function, so it's just a matter of using it in a strategic way.

Be warned however, that if you had implemented your linked list without a tail pointer (where you had to traverse to the end of the list to append), this approach would still work, but would be highly inefficient and not satisfactory.

Here is an example (untested):

List(const List & copy) : head(nullptr), tail(nullptr) 
{ 
     ListNode *copyNode = copy.head;
     while (copyNode)
     {
         append(copyNode->item);
         copyNode = copyNode->next;
     }
 }

Note that this was not tested for boundary conditions, so you may need to check for copy being empty before having to go through the loop.

Here is an example that works for a simple case

Upvotes: 1

Related Questions