142
R.
Sedgewick
N=4
A B C D
B A C D
B C A D
C B A D
C A B D
A C B D
A B A C D B
B A C A D B
C D A B
D C A B
D A C B
A D C B
A D B C
A B C
D A B C
B A C
D B A C
B C A
B D A C
C B A
C A B B A D C
A C B A D B C
C B D A
B C D A
B D C A
-- D B C A
D C B A
C D B A
=2,3,4.
N=2
H
N=
4j
FIGURE 2. Wells' algorithm for N
Neither Wells nor Heap gave recursive
formulations of their methods, although
Boothroyd [1] later gave a recursive imple-
mentation of his version of Wells' method.
Although Wells and Heap undoubtedly ar-
rived at their nonrecursive programs di-
rectly, it is instructive here to derive a
nonrecursive version of Algorithm 1 by
systematically removing the recursion.
The standard method for implementing
a recursive procedure is to maintain a
stack with the parameters and local varia-
bles for each invocation of the procedure.
The simple structure of Algorithm 1
makes it more convenient to maintain an
array
c [ 1 ] , . . . , c [ N ] ,
where
c[i]
is the
value of c for the invocation
permuta-
tions(i).
Then by decrementing i on a
call
and incrementing i on
return,
we ensure
that
c[i]
always refers to the proper value
ofc. Since there is only one recursive call,
transfer of control is implemented by
jumping to the beginning on
call and
jumping
to the place following the call on
return. The
following
program results
di-
rectly when we remove the recursion and
the loops from Algorithm 1:
t:=N;
begtn: c[d:=l;
loop:
if t>2 then t:=t-1 ; go to
begtn
end[f;
re turn: if
c[t]>-t
the n go to extt end[f;
P[B[c#]]]
=:P[t];
c[~]:=c[t] + l;
go
to
loop;
extt"
if
t < N
the n t: =t + 1; go to
return
end[f;
This program can be simplified by combin-
ing the instructions at
begin and loop
into
a single loop, and by replacing the single
go to
exit with
the code at
exit:
t : = N + l ;
loop:
loop while t>2: t . = t - 1 ;
c[t]:=l
repeat;
ret ur n,
if c[t]>-z
the n if
t < N
the n t:=t+l;
go to
ret ur n end[f;
else
P[B[c[t]]]
=:Pit];
c[~]:=c[t] + l;
go to
loop;
end[f;
The program
can be transformed further if
we observe that, after c [N],. •., c [2] are all
set
to 1 (this
is the first
thing that the
program
does), we can do the assignment
c[i]:=l
before
t:=i+l
rather than after
i:=i-1
without affecting the rest of the
program. But this means t h at the loop
does nothing but set i to 2 and it can be
eliminated (except for the initialization),.
as
in this
version:
t:=N;
loop:
c[t]:=l
while z>2.
t:=t-1
repeat;
return"
[f c[t]>-t
then if
t < N
then
c[z]:=l;
~:=t+l;
go to
return
end[f;
else
P[B[c[t]]]: =.P[t ];
c[d: =c[t] +
1;
t:=2;
go to return;
end[f;
Finally,
since the two
go to's in this pro-
gram refer to the same label, they can be
replaced with a single loop. • • repeat. The
formulation
i:=N; loop:
c[~]:=1
while t > 2 : t : = z - 1
repeat;
loop:
[f c[t]<l
then
P[B[c[zJ]]:=:P[z];
c[t]:=c[z]+
1, t:=2;
else
c[t]:=l; t:=t+l;
end[f;
while
t<-N
repeat;
Computing Surveys, Vol 9, No 2, June 1977