One technique that is helpful for working through the maze of links of a general list is to mark processed nodes, as done in Rvisit (section 7.7). It is convenient to cycle through the paths generated by Link[1] ... Link[n] by making Mark an integer: Mark = 0 for an unprocessed node and Mark = i when the Link[i] path is being traced.
Marking the nodes prevents redundant wandering through the structure but does not provide the retracing of a path needed to return to a branchpoint in the traverse. The retracing can be done by reversing the links and using two pointers, Son and Father to bridge positions that temporarily lack a link between them.
The operation of the pointers is most easily seen when it is applied to a linear list, as shown in Figure M.1, (where NIL links have been left blank for clarity). This scheme can be carried out with the help of a temporary pointer Base:
If Son .Mark = 0 then process Son and increment Son
.Mark to indicate that the link is being followed.
If Son .Mark = 1 then examine Son
.Link. If it is NIL then this route cannot be processed further; increment Son
.Mark to indicate that Son is completely processed. If Son
.Link is not NIL then shift pointers to follow Son
.Link, as shown in Figure M.2 .
If Son .Mark = 2 then the path leaving from Son is completely processed. The pointers are then shifted to retrace the path that led to Son, as illustrated in Figure M.3 .
This schematic process can be generalized to nodes with n link fields by incrementing the Mark field each time one of the links leading from a node is followed. The retracing path is followed when Mark = n + 1. An abbreviated trace applied to the example of a general list given at the beginning of section 7.7 is shown in Figure M.4 .
The SUE version of this scheme is:
procedure Visit(p)
FatherNIL
Sonp
repeat
kSon
.Mark
case of k
0 : PROCESS(Son)
Son.Mark
Son
.Mark + 1
1 .. n : if Son.Mark[k] = NIL
then Son.Mark
Son
.Mark + 1
else BaseFather
FatherSon
SonFather
.Link[k]
Father.Link[k]
Base
endif
n + 1 : kFather
.Mark
BaseFather
.Link[k]
Father.Link[k]
Son
SonFather
FatherBase
Son.Mark
Son
.Mark + 1
endcase
until Father = NIL
end {Visit
Projects for fun; for serious students
PJM.1 Implement and test the general visitation algorithm of this section. One way to create a general list for testing is to first place a sparse number of 1's in an N by N table T, with none on the main diagonal T[k,k]. Create an array of N nodes, each of which has N Link fields. If T[i,j] = 1, then for pointer p to node i, set p
PJM.2 A fundamental limitation of this algorithm is that the final value of p
.Link[i] to node [j].
.Mark is n + 1, not 0. A change to modular arithmetic for the Mark field causes infinite loops. (Why?) One solution is to add a switch that causes the counting process to work with an initial mark of either 0 or n + 2. If the switch is global, it can be reset on exit from Visit so that it alternates between two values. Incorporate the necessary changes into Visit and run it. Hint: Let k
| p
.Mark - Switch | and update p
.Mark with a displacement that may be
1 depending on Switch.