Tuesday, July 31, 2012

Find loop in a single linked list & remove it

/* How would you detect a loop in a linked list & remove it? */


#include <stdio.h>
#include <malloc.h>

typedef struct singlelink node;
struct singlelink
{
                int data;
                node *next;
};

void append(node **q,int num);
void display(node *temp);

void append(node **q,int num)
{
    node *temp=*q,*r;
                r = (node *)malloc(sizeof(node));
                r->data = num;
                r->next = NULL;
                if(temp==NULL) *q=r;
                else
                {
                                while(temp->next!=NULL)
                                                temp = temp->next;
                                temp->next = r;
                }
}

void display(node *temp)
{
                printf("\nThe list:\n");
                while(temp)
                {
                                printf("%d ",temp->data);
                                temp=temp->next;
                }
}

void createloop(node *q);
void createloop(node *q)
{
                node *temp=q;
                node *node2=NULL;
                node2=temp->next;
                while(temp->next !=NULL)
                {              temp=temp->next;}
                temp->next=node2;

}


#define DEBUG2              1
void removeloop(node *p, node *tmp);
void removeloop(node *p, node *tmp)
{
                node *temp1=p;
                node *temp2=p;
                unsigned int cnt=1,i;

                /* Count the no. of nodes in the loop */
                while(temp1->next != temp2)
                {
                                temp1 = temp1->next;
                                cnt++;
                }


                /* Fix one pointer to head & the other to cnt^th node from head */
                temp1=temp2=tmp;
                for(i=0;i
                                temp2=temp2->next;


                /* Move both pointers at the same pace, they will meet at the loop starting node */
                while(temp1 != temp2)
                {
                                temp1=temp1->next;
                                temp2=temp2->next;

                }

                /* Get pointer to the last node of loop & make next of it as NULL */
                temp2=temp2->next;
                while(temp2->next != temp1)
                                temp2 = temp2->next;

                temp2->next=NULL;
}



/* Floyd cycle detection algorithm */
void findloop(node *tmp);
void findloop(node *tmp)
{
                /* Have 2 pointers to start of the linked list.
                   Increment one pointer by 1 node and the other by 2 nodes.
                   If there's a loop, the 2nd pointer will meet the 1st pointer somewhere.
                   If it does, then you know there's one.
                */

                node *p,*q;
                p=q=tmp;

                while(p && q && q->next)
                {
                                p=p->next;
                                q=q->next->next;

                                if(p==q)
                                {
                                                printf("Loop detected..\n");
                                                removeloop(p,tmp);
                                                return;
                                }
                }
}




int main(void)
{
                node *head=NULL;
                int i;
                for(i=0;i<10;i++)
                                append(&head,i);
                display(head);

                createloop(head);
                printf("\nOK...\n");
                findloop(head);
                display(head);
                return 0;
}


/*
void findloop(node *tmp)
{
                // Have 2 pointers to start of the linked list.
                //   Increment one pointer by 1 node and the other by 2 nodes.
                //   If there's a loop, the 2nd pointer will meet the 1st pointer somewhere.
                //   If it does, then you know there's one.


                node *p,*q;
                p=tmp;
                q=p->next;
                while(p!=NULL && q!=NULL)
                {
                                if(p==q)
                                {
                                                printf("Loop detected..\n");
                                                removeloop(p,tmp);
                                                return;
                                }
                                p=p->next;
                                q=(q->next)?(q->next->next):(q->next);
                }

}
*/

No comments: