/*方案一:每次循环左移一位,移动k次。*/ void rol(char str[],int n,int k){ assert(k<=n);//assume k is less than n, otherwise we can let k=k%n to meet this requirement. char tmp; for(int i=0;i<k;i++){ tmp=str[0]; memcpy(str,str+1,n-1); str[n-1]=tmp; } } /*方案二:将前k个数拷贝到临时数组中,然后移动后n-k个,再将前k个拷贝到最后。*/ void rol2(char str[],int n,int k){ assert(k<=n);//assume k is less than n, otherwise we can let k=k%n to meet this requirement. char* tmp=new char[k]; memcpy(tmp,str,k); memcpy(str,str+k,n-k); memcpy(str+n-k,tmp,k); delete []tmp; } /*方案三:移动str[0]到临时变量tmp,然后移动str[i]至str[0],str[2*i]至str[i], 以此类推,直到返回str[0]中元素,此时改为从tmp中取值然后终止。 但是这样一次循环移动并不一定可以使所有的元素都移动到最终位置。 这就需要从str[1]开始再次进行移动。总共多少次呢?gcd(n,k)次就可以了。*/ void rol3(char str[],int n,int k){ assert(k<=n);//assume k is less than n, otherwise we can let k=k%n to meet this requirement. char tmp; int cur,next; for(int i=0;i<gcd1(n,k);i++){ tmp=str[i]; cur=i; while(true){ next=cur+k; if(next>=n) next-=n; if(next==i) break; str[cur]=str[next]; cur=next; } str[cur]=tmp; } } //swap a[i..i+n) with a[j..j+n) void swap(char a[],int i,int j,int n){ int tmp; while(n){ tmp=a[i]; a[i]=a[j]; a[j]=tmp; n--; i++; j++; } } /*方案四:ab = ablbr -> brbla。 其中a与br的长度相同。这就将原问题转变为更小的问题了brbl.这个程序中最值得学习的是不变式(invariant)的使用.*/ void rol4(char str[],int n,int k){ assert(k<=n);//assume k is less than n, otherwise we can let k=k%n to meet this requirement. if(k==0||k==n) return; int i,p,j; i=p=k; j=n-i; while(i!=j){ /*invariant: str[0..p-i) in final position str[p-i..p)=a(to be swaped with b) str[p..p+j)=b(to be swaped with a) str[p+j..n-1] in final position */ if(i>j){ swap(str,p-i,p,j); i-=j; } else{//i<j swap(str,p-i,p+j-i,i); j-=i; } } swap(str,p-i,p,i); } //reverse a[i..j]. void reverse(char a[],int i,int j){ assert(i<=j); int tmp; while(i<j){ tmp=a[i]; a[i]=a[j]; a[j]=tmp; i++; j--; } } /*方案五:这个不用说了。*/ void rol5(char str[],int n,int k){ assert(k<=n);//assume k is less than n, otherwise we can let k=k%n to meet this requirement. if(k==0||k==n) return; reverse(str,0,k-1); reverse(str,k,n-1); reverse(str,0,n-1); }
详细请参见《编程珠玑》第二章