<<

Of their party To come to the aid For Now is the time all good PERMUTATION GENERATION men Princeton Robert Sedgewick METHODS University CAVEATS Numerous Q: PROBLEM processing a perm often costs much more than generating it Structural basis for backtracking algorithms Compute exact answers for insights into combinatorial problems Basic research on a fundamental problem Why? can N is be between Generate all N! permutations of N elements published the basis 10 algorithms, and for extremely 20 Motivation dating dumb back algorithms to 1650s 20 19 18 17 16 15 14 13 12 11 10 N 2432902008176640000 121645100408832000 6402373705728000 355687428096000 20922789888000 1307674368000 87178291200 6227020800 479001600 39916800 3628800 number of N perms is between million/sec seconds minutes months weeks years hours impossible day 10 and billion/sec seconds minutes months minute years hours days 20 insignificant trillion/sec seconds minutes month hours days There Q: A: Q: A: Q: Typical Of course!

Does the of edges in input matter? How? How? € It build adjacency-lists representation run input depends are Digression: graph-processing graph-processing graph

2 V 2 graphs, so full employment for algorithm analysts on as the a analysis graph scenario: algorithm of of edges graph (vertex algorithms pairs) What Is Can Same graph with single outlier Complete Ex: there compute a spanning forest (DFS, stop when V vertices hit) best we impact estimate case a digraph simple does cost: the on Digression way edge V V average (right to vertices order reorder average: worst case: average: worst case: edge for € € have (continued) € € a the appears given on

O V edges other (V ln

O V graph? V 2 2 (V first )

(Kapidakis, to 2 graph ) speed on algorithms? all things lists) 1990) up? Goal of analysis Algorithm to compute average No shortage of interesting graphs with fewer than 10 edges Insight faster algorithm to compute average generate Digression: needed, perms, so generate analysis run graph perms of algorithm graph to study algorithms graphs Problem: A B C D D B C A C B D A B C D A Invoke element to the end, then recursively permuting others Compute exch generate(int generate(N); } { { by int for int if

(int all Too { calling (N perms c; (c t exch(c, many i, == = = Method p[i]; N) int 1; 1) of (2N!) a c doit(); N); j) global <= p[i] exchanges 1: generate(N-1); N; array backtracking = c++) p[j]; (!) by exchanging p[j] exch(c, = t; each } N); } D A B C C A D B B A C D A B C D C A B B A C A B C Exercise: Dates Generates all perms with N! exchanges of adjacent elements position in each perm of the other elements Sweep first element back and forth to insert it into every back recursive implementation with constant time per exch to 1650s Method (bell 2: ringing “Plain patterns changes” in English churches) Detail(?): Eliminate first exch in backtracking exch generate(int } { { int for int if General (int Where is new item for { (N c; (c t generate(N-1); i, == = = p[i]; single-exch N) int 1; 1) c doit(); j) <= p[i] N; = exch(?, c++) recursive p[N] p[j]; each time? N); p[j] scheme } = t; } Exercise: E D C B A D A B E C D E A B B C E A D A B C D E D C B A C A D B B C A C D B C B A B A C A B C A: Q: compute an index table from the (known) perm for N-1 1 how do we find a new element for the end? 3 1 1 2 3 Write a program to compute this table so Index table computation all perms of so 3 all takes perms and so forth of into 4 takes into Do we need the table? Table No need to insist on particular sequence for last element Simple Generates perms with N! exchanges Use

specifies generate(int precomputed € } { size recursive Method int for if { is (N

(N c; (c generate(N-1); N(N-1)/2 == − algorithm = 1 index 3: )! N) 1; 1) (N general c doit(); − table but 2 <= )! ...3 N N; is recursive ! exch(B[N][c], 2 c++) less ! different algorithms than 20 single-exch 9 7 7 5 5 3 3 1 1 7 8 1 2 3 4 1 2 1 5 1 5 7 1 3 3 3 N); 3 6 5 2 5 2 1 1 5 3 1 3 3 } 9 4 3 2 1 7 9 7 3 5 2 1 3 3 1 D C B A C B A D B A C D A B C D C B A B A C A B C *Note: Exercise: Index Q: where can we find the next element to put at end? A: no table at relationship Prove that it works! 1 is if Method not N between is needed odd; 4: Heap i if Heap’s* and N is heap even data algorithm structure Starting point for code optimization techniques N! Simple recursive generate(int exchanges } { Implementation int for if } { (N c; (c exch(N generate(N-1); == = N) 1; 1) % c { 2 <= doit(); of ? 1 N; Heap’s : c++) c, return; N) method } (recursive) N! exchanges saved when test succeeds Simple recursive function generate(int } { Implementation int for if } { (test(N)) c; (c exch(N generate(N-1); = N) 1; % c 2 return; <= easily adapts to backtracking of ? 1 N; Heap’s : c++) c, N) method (recursive) Use as control structure to generate perms 1-1 correspondence with permutations (Can Values of digit i range from 1 to Count

for for commonly used to generate random perms for derive c[n] if else using (n (n (i (c[n] = = = c[n++] a code = mixed-radix 1; 1; 1; 1; < by n n i n) = <= <= systematic Factorial <=N 1; { N; N; c[n]++; i++) number ) n++) recursion exch(i, system n = 1; removal) random(i)); } BDCA BACD BACD ABCD 1234 1134 1224 1124 1214 1114 1233 1133 1223 1123 1213 1113 1232 1132 1222 1122 1212 1112 1231 1131 1221 1121 1211 1111 “Plain changes” and most other algs also fit this schema generate(int } { Implementation int for for doit(); } { { n, (n (n if p[n] else } { t, = = (c[n] doit(); c[n]++; exch(N N) 1; 1; = c[n++] M; n; n n < <= <= c[n] n) % of = n N; N; 2 1; = Heap’s = ? ) 1; n++) 1; 1 : } c, method N) (nonrecursive) € € Typical running time: Therefore Solve Recurrence for B Most € A(N): B(N): B(N) B(N) N! statements by = the number of tests for N equal to 1 (loop iterations)

= dividing the NB(N

B(N) B(N ( N € extra − − Analysis − 1 = 1) 1) )! by are  N! + + € cost N! 1 ( 19N N! executed 1 e and for − = for ! 1 worthwhile of 1 + ) A(N 

telescoping + N

N and Heap’s 2 1 > ! € N! ) odd + 1 + with similarly 3 1 times € 10B(N to ! + lower ... method

B( (by ) + 1) constant ≈

A N! 1 (N = 36.55N design) 1 ) =  N! ! except huge / e  quantity Starting point for code optimization techniques N! generate(int exchanges Improved } { int if for } { } { (N c; (c doit(); exch(N p1 generate(N-1); p[1] p[1] p[1] p[2] p[1] == = = version N) 3) 1; = = = = p[1]; = % p2; p1; p3; p1; p3; c 2 <= ? p2 p[3] p[2] p[3] p[1] p[2] of 1 N; = Heap’s : c++) = = = = p[2]; = c, p1; p3; p2; p2; p2; N) method p3 doit(); doit(); doit(); doit(); doit(); = p[3]; (recursive) return; Lower Bound: about (1/6) billion perms/second Quick empirical Heap Heap (nonrecursive) !! about 2N! register transfers inline inline study (recursive) !! cc cc N N Java !! on -O4 !! -O4 !! = = Bottom this 3 !! 2 !!

machine 442.8 415.2 51.7 92.4 84.0 54.1

3.2 line secs secs secs secs secs secs secs (N = 12) [see Wells Trotter Sedgewick Ord-Smith Knuth Heap CACM, Computing Surveys, 1977 Computer Journal, 1970-71 //www-cs-faculty.stanford.edu/~knuth/taocp.html Computer Journal, 1963 , “Permutations by interchanges,” surveys , Elements of combinatorial computing, 1961 , The , “Perm , Permutation Generation Methods, , “Generation of permutation ,” 1962 Art for (Algorithm of many Computer more] References 115),” Programming, vol. 4 sec. 7.2.1.1 Initial 10 20 30 40 50 60 0 results Digression: 10 20 30 40 50 60 0 (Dagstuhl, analysis 2002) 10 20 30 40 50 60 0 of graph 10 20 30 40 50 60 0 algorithms 10 20 30 40 50 60 0