今天又发现一个关于完美洗牌的算法。这个比较简单一些,由 microsoft的Peiyush Jain提出。 ?  
原论文:      A Simple In-Place Algorithm for In-Shuffle. ?  
                 Peiyush Jain, Microsoft Corporation. ?                             July 2004 ? 问题描述: ? 所谓完美洗牌算法即是把输入为: ? a_1,a_2........a_n,b_1,b_2.........b_n的序列变为 ? b_1,a_1,b_2,a_2.......b_n,a_n 这是in perfect shufle。相对应的还有out perfect shuffle。两者区别在于首尾元素位置变或不变。 ? perfect shuffle算法要求在O(n),时间内,O(1)空间内完成。 ?  
perfect shuffle实质是一个置换。置换为: ?                                        i -> 2*i mod (2*n+1) ? 由于置换可以分解为一系列不相交的轮换之积。故如果能找出所有轮换的一个代表元则可很容易解决问题。 ? 如   ? n=3时 输入 1  2  3  A  B  C b   => A   1   B   2   C   3所对应的轮换为(1,2,4)(3,6,5) ? 选代表元为1和3以及一个临时变量T: ?                             2->T,1->2 ?                             1  2  3   A   B   C  -----------> _  1  3   A   B   C                         4->1,T->4     _  1  3   A   B   C  ----------->  A  1  3   2   B   C                     ?                            6->T,3->6 ? A  1  3   2   B   C  -----------> ?A  1  _   2   B   3                           5->3,T->5 ? A  1  _   2   B   3  -----------> ?A  1  B   2   C   3   置换完成  ? 因此问题就转换为求置换的轮换分解中的代表元问题了。 ? 文中巧妙的利用特定条件下每个不相交的轮换可有3的不同幂次生成?。   见论文:A Simple In-Place Algorithm for In-Shuffle.                   Peiyush Jain, Microsoft Corporation.  1、问题描述:  所谓完美洗牌算法即是把输入为:  a_1,a_2........a_n,b_1,b_2.........b_n的序列变为  b_1,a_1,b_2,a_2.......b_n,a_n 这是in perfect shufle。 perfect shuffle算法要求在O(n),时间内,O(1)空间内完成。   
perfect shuffle实质是一个置换。置换为:                                         i -> 2*i mod (2*n+1)  由于置换可以分解为一系列不相交的轮换之积。故如果能找出所有轮换的一个代表元则可很容易解决问题。  如 len=3时 输入 1  2  3  A  B  C b   => A   1   B   2   C   3所对应的轮换为(1,2,4)(3,6,5)  选代表元为1和3以及一个临时变量T:                       1  2  3   A   B   C  ----------->  2->T,1->2    _  1  3   A   B   C  ----------->   4->1,T->4                 A  1  3   2   B   C  -----------> 6->T,3->6               A  1  _   2   B   3  -----------> 5->3,T->5  A  1  B   2   C   3   置换完成  因此问题就转换为求置换的轮换分解中的代表元问题了。  文中巧妙的利用特定条件下: 即(2的任意次幂)对(3的k次幂)取模,能得到一个轮换环,并且环与环之间刚好互不相交 。  如我们分析长度2*n=3^k-1的置换的轮换分解。 (若长度为2*4=8,则8=3^2-1) 考虑某一包含3^s( 1 =< s < k )的轮换。不妨记3^s为a_1,3^k记为m。  则轮换里的数分别为:    a_2 =  2* a_1 mod m    a_3 =  2* a_2 mod m;    a_4 =  2* a_3 mod m;       。。。。。 。。。   a_len = 2* a_len-1 mod m    a_1 = 2* a_len   mod m  则  a_1  ≡2^len * a_1 mod m;  ( 最后一项中的a_len用倒数第二行乘2替代,以此类推........) , 依此,假设m=9,可以确定每个轮换中,len的值, 如a_1=3^s=3^0=1,则1=2^len * 1 mod m,则 len=2; 如a_1=3^s=3^1=3,则3=2^len * 3 mod m,则 len=6   因此每个3^s开始的一个轮换满足 :   3^s ≡3^s * 2^len mod 3^k ,且轮换的长度为len。 补充:若对1 2 3 4 5 6 7 8 9 10进行洗牌则首先交换成 1 2 3 4 6 7 8 9 5 10   (n=4,因此我们只对需要的前8个先调整到前面) 下面举了个例子:洗牌置换过程例证,它例举了将1234ABCD置换成A1B2C3D4的过程,请将图中的n理解为len,k=2。  |