Search code examples
c++pointerscircular-list

Circular linked list in C++ (insert at beginning)


I am studying old exams for an exam. One task is to implement an insert and print function that inserts elements at the beginning of a circular list. A program is provided to test the students solution.

My solution for the insert is:

void Circular_List::insert(std::string const& str)
{
    if (entry == nullptr) {
        entry = new Element(str);
        entry -> next = entry;
    }
    else {
        Element* temp = entry;
        entry = new Element(str);
        entry -> next = temp;
    }
}

My thought process: enter image description here

It seems to work because my print:

void Circular_List::print() const
{
    Element* temp = entry;
    while (temp -> next != temp) {
        cout << temp -> name << endl;
        temp = temp -> next; 
    }
}

prints the list in the right order EXCEPT for the element that I first added. I don't understand why it doesn't print the first element. The program provided prints out 20 iterations. For example if I insert a,b,c,d,e the program will print

d->c->b->a->a->a->a->a->a->a->a->a->a->a->a->a->a->a->a->a->

This seems very off, should it not loop to the front of the list instead of just printing a?

The test program:

  int j = 0;
  for (Circular_List::Iterator i = l.begin(); i != l.end() && j < 20; ++i, ++j)
  {
    cout << *i << "->";
  }
  cout << endl;

class Iterator
  {
  public:
    Iterator(Element* e) : pos(e) {}
    ~Iterator() = default;
    Iterator(Iterator const&) = default;
    Iterator& operator=(Iterator const&) = default;
    bool operator!=(Iterator const& i) { return pos != i.pos; }
    operator bool() { return pos != nullptr; }
    Iterator& operator++() { pos = pos->next; return *this;}
    std::string operator*() { return pos->name; }
  private:
    Element* pos;
  };

I assume my insert is wrong but I can't figure out what I'm doing wrong?


Solution

  • When you are inserting the second element to the list, your first element keeps next entry pointing back to itself. You need to update two next fields: one in inserted record and another in the list to point back to inserted record. You fail to do the latter. The else clause should LIKELY be:

        Element* temp = new Element(str);
        temp->next = entry->next;
        entry->next = temp;
        entry = temp;
    

    This makes entry a pointer to LAST cycle element and entry->next - the first cycle element;

    BTW, your second drawing is incorrect as 'a'->next should be pointing back to 'a' and not to entry.