Determine whether a single-chain table has a ring and determine whether the two linked lists overlap (reprinted)
【Abstract】 there is a single-chain table, where there may be a ring, that is, the next of a node points to the node in the linked list before it, thus forming a ring at the end of the linked list. 1. How to determine whether a linked list is such a linked list? 2. If the linked list shows an existing ring, what if the entry point of the ring is found? Extension: determines whether two single-chain tables are intersecting. If yes, the first point of the intersection is given.
There is a single-chain table, where there may be a ring, that is, the next of a node points to the previous node in the linked list, so that a ring is formed at the end of the linked list.
Problem:
1. How to determine whether a linked list is such a linked list?
2. If the linked list shows an existing ring, what if the entry point of the ring is found?
Answer:
1. Determine whether the linked list has a ring. The method is as follows:
Set two pointers (fast and slow). The initial values all point to the header. Slow moves one step forward each time, and fast moves two steps forward each time. If the linked list has a ring, fast must first enter the ring, when slow enters the ring, the two pointers must meet each other. (Of course, if the first line to the end of fast is null, It is a loop-free linked list) The program is as follows:
Bool isexitsloop (slist * head)
{
Slist * slow = head, * fast = head;
While (Fast & fast-> next)
{
Slow = slow-> next;
Fast = fast-> next;
If (slow = fast) break;
}
Return! (Fast = NULL | fast-> next = NULL );
}
2. Find the entry point of the ring
When fast encounters slow, slow certainly does not traverse the linked list, and fast already loops n circles (1 <= N) in the ring ). Assume that slow takes the s step, then fast takes 2 s step (the number of fast steps is equal to the number of S plus N turns on the ring), set the ring length to R, then:
2 S = S + nR
S = nR
Set the length of the entire linked list to L. The distance between the entrance ring and the encounter point is X, and the distance from the start point to the entrance point is.
A + x = nR
A + x = (n-1) R + r = (n-1) R + L-
A = (n-1) R + (L-a-x)
(L-a-x) is the distance from the encounter point to the ring entry point. From this point, we can see that from the chain table header to the ring entry point is equal to (n-1) the cycle inner ring + the encounter point to the ring entry point, so we set a pointer from the head of the linked list and from the encounter point. Each time we take a step, the two pointers must meet each other and the first point of the encounter is the ring entry point.
The program is described as follows:
Slist * findloopport (slist * head)
{
Slist * slow = head, * fast = head;
While (Fast & fast-> next)
{
Slow = slow-> next;
Fast = fast-> next;
If (slow = fast) break;
}
If (fast = NULL | fast-> next = NULL)
Return NULL;
Slow = head;
While (slow! = Fast)
{
Slow = slow-> next;
Fast = fast-> next;
}
Return slow;
}
An easy-to-understand explanation is provided:
An O (n) method is (two pointers, one increment step at a time, and one increment step at a time. If there is a ring, the two will inevitably overlap, and vice versa ):
The most vivid metaphor for this solution is running in the playground, which will take the lap of the slow speed.
It can be proved that when P2 catches up with P1, P1 must have not completed the loop, and P2 will not catch up with it after Multiple Laps across P1.
We can prove from the gap between P2 and P1 that P2 will catch up with P1 but will not skip
Because P2 takes two steps at a time, and P1 takes one step, the gap between them is reduced step by step. When, 0, and 0, the gap will overlap.
Based on this method, it can be proved that P2 does not always speed up detection after taking more than three steps at a time, but may not identify loops.
Since we can determine whether there is a loop, how can we find the entrance to this loop?
The solution is as follows: when P2 follows two steps each, and P1 follows one step each, it is found that P2 and P1 overlap, and the one-way linked list has a loop.
Next, let P2 return to the head of the linked list and re-walk. Each step does not go 2, but 1. When P1 and P2 meet again, it is the entrance of the loop.
This can prove:
When P2 and P1 met for the first time, assuming that P1 took n steps and the loop entrance was completed during step P
Path of P1: P + c = N; C is the intersection of P1 and P2, and the distance from the loop entry
P2 path: P + C + K * l = 2 * n; L indicates the circumference of the loop, and K is an integer.
Obviously, if P1 takes n steps again from P + C, it can return to P + C.
At the same time, if P2 starts from the beginning, after N steps, it will reach P + C.
Obviously, in this step, P1 and P2 only follow different paths in the previous P step, so when P1 and P2 overlap again, it must be at the loop entry point of the linked list.
Expansion problems:
Determines whether two single-chain tables are intersecting. If yes, the first vertex of the intersection is given (both linked lists do not have loops ).
There are two better methods:
1. Connect one of the linked lists to the beginning and end, and check whether the other linked list has a ring. If so, the two linked lists are intersecting, and the detected dependency ring entry is the first vertex of the intersection.
2. If the two linked lists intersect, the two linked lists are the same nodes from the intersection to the end of the linked list, we can traverse one linked list first until the end, and then traverse another linked list, if you can also go to the same end point, the two linked lists will intersection.
Now let's write down the length of the two linked lists and traverse them again. The long chain table node starts to step forward (lengthmax-lengthmin), and then the two linked lists move forward simultaneously, each step, the first point of an encounter is the first point of the intersection of two linked lists.