算法:完美洗牌算法:一个长度为2n的(整型)数组元素为 a1 a2 ... an b1 b2 ... bn

来源:互联网 发布:淘宝模特网拍培训 编辑:程序博客网 时间:2024/05/11 03:59
问题描述:一个长度为2n的数组元素为 a1 a2 ... an b1 b2 ... bn
要求: 用O(1)的空间代价, 在O(n)时间内把数组变成 b1 a1 b2 a2 b3 a3 ... bn an (分治法时间复杂度O(nlogn))


采取置换的方法,当需要保证似乎循环无遗漏置换。需要用到数论原根等证明定理。
http://user.qzone.qq.com/414353346/blog/1243343118#!app=2&via=QZ.HashRefresh&pos=1243343118
算法论文:http://arxiv.org/pdf/0805.1598.pdf

自己的算法实现:
int static findMaxNear(int length){int k=3;while(k-1<length) k*=3;if(k-1==length)return k-1;elsereturn k/3 - 1;}void reverse(int a[],int start,int end){for(int i=start,j=end;i<j;i++,j--){int tmp=a[i];a[i]=a[j];a[j]=tmp;}}void rightmove(int a[],int start,int end,int steps){reverse(a,start,end);reverse(a,start,start+steps-1);reverse(a,start+steps,end);}void static shuffle_3k(int a[],int start,int length){int cyclestart=1; //3^0while(cyclestart<=length){ //length==3^k-1,cyclestart=1,3^1,...,3^(k-1)int tmp=a[start+cyclestart-1],nexttmp;int nextpos=2*cyclestart%(length+1); //nextpos为当前元素移动到的位置while(nextpos!=cyclestart){ //直到回到起点nexttmp=a[start+nextpos-1];a[start+nextpos-1]=tmp;tmp=nexttmp; nextpos=nextpos*2%(length+1);}a[start+cyclestart-1]=tmp;cyclestart*=3;}}void perfect_shuffle(int a[],int start,int length){int startpos=start,end=start+length-1;while(startpos-start<length){int cur_length=end-startpos+1;int m=findMaxNear(cur_length);//i=3^k-1<=Nif(m<cur_length) //还有剩余序列,则需要循环右移m/2个单位rightmove(a,startpos+m/2,startpos+cur_length/2+m/2-1,m/2);shuffle_3k(a,startpos,m);//分别以1,3,9,...,3^k为首元素开始循环置换startpos+=m;}}#define N 100void main(){int data[N]={0};int i=0;int n;printf("please input the number of data you wanna to test(should less than 100):\n");scanf("%d",&n);if(n&1){printf("sorry,the number should be even ");return;}for(i=0;i<n;i++)data[i]=i+1;perfect_shuffle(data,0,n); //in perfect_shuffle 首位均改变for(i=0;i<n;i++)printf("%d   ",data[i]);}




输入:10
即:  1 2 3 4 5 6 7 8 9 10

输出: 6 1 7 2 8 3 9 4 10 5   



原创粉丝点击