remove a loop from a linked list

Lets consider an example of a linked list contained a loop:

1--> 2--> 3--> 4--> 5-->6-->7 (connected back to 5)

how to detect the loop and how to remove the loop from the last node of the linked list?

  1. template <class T>
  2. void List<T>::removeLoop()
  3. {
  4.     if( head == NULL )
  5.         return ;
  6.     Node<T> *ptr1 = head, *ptr2 = head ;
  7.     do
  8.     {
  9.         ptr1 = ptr1->next ;
  10.         ptr2 = ptr2->next ;
  11.         if( ptr2 != NULL )
  12.             ptr2 = ptr2->next ;
  13.     }
  14.     while( ptr2 != NULL && ptr2 != ptr1 ) ;
  15.     if ( ptr2 == NULL )
  16.         return ;
  17.     if( ptr2 == head )                //for fully circular lists!    
  18.     {
  19.         while(ptr2->next != head )
  20.             ptr2 = ptr2->next ;
  21.         ptr2->next = NULL ;        
  22.         return ;
  23.     }
  24.     ptr1 = head ;
  25.     while( ptr1->next != ptr2->next )
  26.     {
  27.         ptr1 = ptr1->next ;
  28.         ptr2 = ptr2->next ;
  29.     }
  30.     ptr2->next = NULL ;

Consider a linked list having a loop. Its mathematical model can be designed something like this -

A straight chain containing 'm' nodes, the last of which is linked to one of the 'n' nodes that are connected in cyclic fashion. So the culprit link you can find by advancing m+n-1 links, and removing the last one. Now the question is how to do it?

Consider first the method to detect the link -

If p1 and p2 are two pointers that start at head, and p1 advances by 1 step in each interation and p2 by 2 steps, then they surely would meet at one of the nodes that are in the loop. Let the offset of this node (with respect to the first node of the loop, that is directly pointed
to by the last node of the straight chain, as 0) be k,

where 0 <= k < n

Let p1 be advanced by x steps, so p2 would have advanced by y = 2*x

steps. We can model x as -

x = m + r*n + k

where r is the number of cycles of the loop the pointer p1 travelled before it met p2 at the kth node (where r >= 0).

Then for p2

y = 2*x = 2*( m + r*n + k )
  = 2*m + 2*r*n + 2*k

or

y = ( m + 2*r*n + k ) + (m + k)

for both p1 and p2 to meet at the kth node after x and y steps respectively, we can assert that

(m + k) should be an integral multiple of n,

or m + k = i*n
or k = i*n - m

since k >= 0, i should be the such that k comes out to be positive,

also i should be as small as possible, because the loop will terminate once p1 and p2 are equal.

If m+k is a multiple of n, then advancing a pointer m steps from the node where p1 and p2 met, should fetch the culprit node, the next pointer of which you can set to null to terminate the link. But theoretically, it is impossible to find m and k separately in O(n) time. So a simple trick can be employed, keep a pointer at the kth
node, and another at head, advance both one step each synchronously till, the next pointer of each is not equal, this condition would be precisely true for the culprit node only. So that solves the problem.

The only exception where this fails is when m is zero, that is the list is a fully circular linked list. In that case you can check to find this case by testing whether the kth node found is same as the head itself, if so, simply traverse the loop once to find the node pointing
to the head and set its next pointer to null!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值