0

My code is about detecting a loop / cycle in a linked list, and then removing the error. However, only the first element of the linked list is getting printed after running the code to remove the loop / cycle.

I have already tried merging the detectCycle() and removeCycle() functions, but it has no impact on the output.

class ListElem
{
public:
    int value;
    ListElem *next;   //Pointer used to make link
};


int length(ListElem *head)   //function to check length of linked list
{
    int len = 0;
    while(head != NULL)
    {
        head = head -> next;
        len += 1;
    }
    return len;
}



void insertAtTail(ListElem *&head, ListElem *elem)    //if the list is non - empty, the insertAtTail algorithm
                                                        //does not change the head of the list
{
    ListElem *lastElem;   //lastElem will point to the last element

    if ( head == NULL ) // Detect and handle exception case....    (in case the list is empty)
   {
      head = elem;
      elem->next = NULL;
   }

   else
   {
       lastElem = head;

        while(lastElem->next != NULL)     //Find the last element in the list

        {

            lastElem = lastElem->next;

        }

        lastElem->next = elem;   // Link "elem" to lastElem:
        elem->next = NULL;      // Mark new elem as the last element:

    }
}

void buildList(ListElem *&head)
{
    int data;   // data = the value of elements to be inserted in linked list that will be input by the user
    cin>>data;
    ListElem *p;


    while (data != -1)    // when the user inputs '-1', the process of taking input will stop
    {
        p = new ListElem;
        p -> value = data;

        insertAtTail(head, p);
        cin>>data;
    }
}

void Print(ListElem *head)
{
   ListElem *p;

   p = head;             // Very important: start at first element

   cout << "List ==> ";
   while ( p != NULL )
   {
      cout << p->value << "  ";  // Access value stored in list element
      p = p->next;               // Visit next element in list
   }
   cout << "\n\n";
}


void removeCycle(ListElem *head, ListElem *fast)
{
    ListElem *slow = head;

    while(slow ->next != fast -> next)   // ensures that slow pointer does not go past the fast pointer, and detects the
    {                           // node at which slow and fast pointers point to the same node
        slow = slow -> next;
        fast = fast -> next;
    }


    fast -> next = NULL;   // This works when the end of the loop is reached and the “next” pointer to that node
                            //is made NULL representing the end of a linked list without loop


}

bool detectCycle(ListElem *head)
{
    ListElem *slow = head;
    ListElem *fast = head;


    while(fast != NULL && fast -> next != NULL)
    {
        fast = fast -> next -> next;
        slow = slow -> next;

        if(fast == slow)
        {
            removeCycle(head, fast);  // this will call the remove cycle function to remove the cycle. The position
                                    // of the fast pointer is to be retained, 
 so it is passed as argument to the
            return true;               // remove cycle function
        }
    }
       return false;
}
int main()
{
    ListElem *head = NULL;

    buildList(head);

    /* Deliberately create a loop/cycle for testing */
    head->next->next->next->next->next = head->next->next->next;

    if(detectCycle(head))
    {
        cout<<"A loop was present, and has been removed. List after removal of loop is :"<<endl<<endl;

        Print(head);
    }
    else
    {
        cout<<"A loop was not present"<<endl;
        Print(head);

    }

    cout<<"The length of the list is : "<<length(head);
    cout<<endl<<endl;
    return 0;
}

I expect the Print() function to output the entire corrected list.

  • Could you add the following. 1) The input you use when it doesn't work, 2) What you expect the corrected list to look like. – john Aug 10 '19 at 19:21
  • Hi. 1)`1 2 3 4 5 6 7 8 9 -1`can be taken as an example . 2) The corrected list should just display all the elements in the sequence in which they were input. The cycle / loop should be removed by the removeCycle() function. – Sehajbir Thind Aug 10 '19 at 19:45
  • 1
    @SehajbirThind look at your detect cycle. What are the initial values of `fast` and `slow` the *first* time they enter the loop? They both refer to `head`, right? So what is the very first thing done in that loop? `if(fast == slow) break;`. Since they're equivalent (you just set them to be so), that loop is completely pointless, breaks immediately and you always run `removeCycle` on the head pointer no matter where the cycle is (if there even is one) or what's in the list. Run this in a *debugger* to see it first-hand. You're not positioning `fast` correctly on initial setup. – WhozCraig Aug 10 '19 at 19:50
  • @WhozCraig Thanks for the reply. I have made changes in the detectCycle() function. However the code is now printing just the first 5 elements of the corrected list. – Sehajbir Thind Aug 10 '19 at 20:18
  • Different bug, and more fuel to the mantra of "use a *debugger*" – WhozCraig Aug 10 '19 at 20:40
  • @SehajbirThind You create a cycle by overwriting one of your next links. This is a destructive operation, the overwritten link is lost. You can remove the cycle, but putting it back to how it was before is impossible because there is no way of knowing where the cyclic link was pointing to before. – john Aug 10 '19 at 20:42
  • @SehajbirThind And of course if you look at your code it does this `fast -> next = NULL;` to remove the cycle. That doesn't put things back to how they were before, but you can't do any better. So your expectations are unrealistic. – john Aug 10 '19 at 20:47
  • Actually your logic is not correct in removeloop() because it is not sure that fast and slow will be corresponding to the linked node. They can be representing any different node also. – learner-coder Aug 11 '19 at 02:53

0 Answers0