19 89 10 21 106 15 99 56 111 42 128
The first step is to build an index by reading the keys into an array, and associating each one with its position. This represents the location of the record which possesses the key:
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
19 | 89 | 10 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | key | |||||||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | record location |
Then sort this index by the key values:
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 42 | 56 | 89 | 99 | 106 | 111 | 128 | key | |||||||||||
3 | 6 | 1 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | record location |
The locations are then applied back to the yet unsorted records, where they act as "come from" indicators. That is, they tell where the record in each position should come from when the records are sorted:
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
19 | 89 | 10 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
3 | 6 | 1 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from |
For instance, location 2 should contain the record presently at location 6.
Now the table sort algorithm begins. Note that in the index, the key values stand only for themselves. In the table sort, they stand for their entire record. It proceeds by looking for cycles. The outer loop scans through the list with the pointer cycstart to find the start of a cycle. A cycle is detected wherever a record is found which is not in its correct final position.
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
19 | 89 | 10 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
3 | 6 | 1 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
cyscan |
In this case, the first iteration of the outer loop detects a cycle, because position 1 should contain the record from position 3. The cycle is a chain of come from values which travels through the array back to its starting point. In the present case, the cycle we have detected at position 1 is very short: just 1, 3, and back to 1. We run the inner loop which follows that cycle. We initialize by moving the data from position 1 into a temp, and set cycscan to equal cycstart:
temp = 19
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
19 | 89 | 10 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
3 | 6 | 1 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
The inner loop executes one time: it moves the record from location 3 to 1, then moves the scanner on to 3 following the cycle:
temp = 19
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 89 | 10 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 6 | 1 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
The inner loop then exits after this single iteration, because we have reached the end of the cycle. We then leave the loop, and restore the record from temp into location 3, completing the cycle.
temp = 19
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 89 | 19 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 6 | 3 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
Notice how the come from values of positions 1 and 3 have changed to be 1 and 3, respectively, indicating that the records in those locations are the correct ones. Whenever we place a record into its correct position, we set its come from equal to its location since the location needs the record it contains.
The outer loop then advances cystart, and finds another cycle at 2, since position 2 should contain the data in position 6.
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 89 | 19 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 6 | 3 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
cyscan |
The cycle at this position is longer than the previous one, going 2, 6, 8, 7, 2. To see this, simply follow the chain of come from values. We prepare for the inner loop which follows the cycle:
temp = 89
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 89 | 19 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 6 | 3 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
Now, the inner loop will follow the chain of come from pointers. At each step, it moves the record into the location given by cyscan which belongs there, then advances cyscan to the next location, which is the source of the record.
temp = 89
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 15 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 8 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
temp = 89
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 56 | 99 | 56 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 6 | 2 | 7 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
temp = 89
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 56 | 99 | 99 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 6 | 2 | 8 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
Now, the inner loop halts because the cycle has been closed. We have reached the location which requires the record from the starting point. After we exit the inner loop, we move the value in temp (which originally came from location 2) into location 7.
temp = 89
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 56 | 89 | 99 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 6 | 7 | 8 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
Again, notice that whenever we move data into a location, we change the come from of the receiver to indicate that it should contain the record it does contain.
Now, the outer loop advances to position 3.
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 56 | 89 | 99 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 6 | 7 | 8 | 5 | 9 | 11 | come from | |||||||||||
cyscan |
Since location 3 contains the data is should have, there is no cycle at 3, and the inner loop is not run. Likewise for position 4. When the outer loop reaches position 5, we find the cycle 5, 10, 9, 5, and begin the inner loop:
temp = 106
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 106 | 56 | 89 | 99 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 10 | 6 | 7 | 8 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
temp = 106
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 42 | 56 | 89 | 99 | 111 | 42 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 5 | 9 | 11 | come from | |||||||||||
![]() | cyscan |
temp = 106
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 42 | 56 | 89 | 99 | 111 | 111 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 5 | 10 | 11 | come from | |||||||||||
![]() | cyscan |
Then, leave the inner loop and restore the temp value:
temp = 106
![]() | cystart | |||||||||||||||||||||
[1] | [2] | [3] | [4] | [5] | [6] | [7] | [8] | [9] | [10] | [11] | ||||||||||||
10 | 15 | 19 | 21 | 42 | 56 | 89 | 99 | 106 | 111 | 128 | record | |||||||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | come from | |||||||||||
![]() | cyscan |
We then return to the outer loop, which continues from position 6. It encounters no new cycles (all records are in position) and will quietly finish without running the inner loop again, or moving any more records.