您的位置:首页 > 职场人生

读程序员编程艺术第一章---左旋字符串(三)

2014-03-18 10:19 344 查看
STL中的循环移位法用到了gcd原理。gcd原理的实现是简单的欧几里得算法又称辗转相除法,这里就不在赘述了。

对于数组的循环移位,可以采用的方法一共有四种。

1、将数组拷贝复制到相同长度的数组之中,改变顺序,并拷贝回原来的数组。

2、先交换前面的能够交换的部分,在处理尾巴。如上一遍中的指针翻转法就是这么做的。

3、分组交换。

4、所有序号为(j+i*m)%n(j表示循环的起始链位置,i为计数变量,m为左旋位数,n表示字符串长度),会构成一个循环链(共有gcd(n,m)个),每个循环链上的元素只要移动一个位置既可,最后整个过程一共交换了n次(每一个循环链长n/gcd(n,m),总共有gcd(n,m)个循环链)。

下面我们来看一个简单的例子:

字符串abcd需要左旋维dabc,可以知道n=4,m=3。

根据4中的方法:

1、j=0,即起始位置为0;

2、得到循环链

for i=0:n-1

int k=i*m%n;

end;

得到循环链是0,3,2,1

3、我们根据这个循环序列复制一遍即可得到想要的结果。

temp=ch[0],ch[0]=hc[3],ch[3]=ch[2],ch[2]=ch[1],ch[1]=temp;

即abcd-->_bcd-->dbc_-->db_c-->d_bc-->dabc;

很奇妙是吧。

上面是对于m,n互为质数的情况,现在我们讨论一下m,n不是互为质数情况。此时循环链不止一个,我们只要把每个循环链依次的执行一遍既可以得到我们想要的结果。所有序号为(j+i*m)%n(其中j为0到gcd(n,m)-1之间的某一个数,i=0:n-1)会构成一个循环,一共有gcd(n,m)个循环链。

可以编写代码 如下:

#include"stdafx.h"
#include<stdio.h>
#include"string"
#include"iostream"
using namespace std;

//求最大公因数
int gcd(int m,int n)
{
//递归出口
if(m%n==0)
return n;
else
{
//设置临时变量,防止m丢失
int temp=m;
m=n;
n=temp%n;
//递归
gcd(m,n);
}
}

//定义左旋函数
void rotate(string &str,int m)
{
//字符串长度
int lenofStr=str.length();
//循环链的个数,也即是外层循环的次数
int numofGroup=gcd(lenofStr,m);
//每个循环链的个数,也即是内层循环的次数
int elemInSub=lenofStr/numofGroup;

for(int j=0;j<numofGroup;j++)
{
char temp=str[j];
int i;
//一次循环链的交换
for(i=0;i<elemInSub-1;i++)
{
str[(j+i*m)%lenofStr]=str[(j+(i+1)*m)%lenofStr];
}
str[(j+i*m)%lenofStr]=temp;
}
}
int main()
{
string str="abcdef";
cout<<str<<endl;
rotate(str,3);
cout<<str<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: