将一个具有n个元素的一维向量向左旋转i个位置.假若n = 8, i = 3, 那么向量abcdefgh 旋转后为defghabc.

(文中代码部分,均为我用c语言实习.编译器为vc6.若出现错误或者有更好的方法请,请留言交流.谢谢~) 

1、将待旋转的向量看作是ab两段,假设a比b短,将b分割为b1和b2使b2长度与a相等.

交换a、b2,这样ab1b2变为b2b1a这样a已经在自己最终的位置上了.下面的工作就变成了旋转b2b1.

/**********************************

       Fction:将字符串按条件转置

       char * p:字符串首地址

       int t:所要选择部分的长度

       int n:串的总长度

Return:void

      

**********************************/

void  Q(char *p,int t,int n){

 

         char tmp;

         int i;

         int flag = 0;                                   //标记变量

         char *p1 ;                                     //用于指向b2的头地址

         if(n !=1 && n != 0)

         {       

/*********************************************

                   判断t即所要旋转的长度是否大于另一部分,因为我们

                   选择短的那部分,相应的分解长的那部分.所以若t>n-t

                   则把短的那部分赋值给t

*********************************************/

                   if(t>n-t){

                            t = n-t;

                            flag = 1;

                   }

                   //对b2串头地址的初始化

                   p1 = p+n-t;

                   //开始交换变量

                   for(i = 0;i<t;i++){

                            tmp = *(p1+i);

                            *(p1+i) = *(p+i);

                            *(p+i) = tmp;

                   }

/*********************************************

                   根据标志位选择递归

                   若形参t即为分解部分即ab(这里假设a比b短)

                   则a已经在最终位置固串首地址不变,t不变,所选择串总长度-t

                   若是ba,则t为需分解的串的长度.这里为了简化代码

                   我们还把b1b2a看成ab1b2固上文对t赋值n-t

                   但a被换置前端亦为最终位置固.总串首地址后移t

                   而总长度-t,下次所旋转的长度在n-t的基础上再-t

*********************************************/

 

                   if(flag)

                            Q((p+t),n-2*t,n-t);

                   else

                            Q(p,t,n-t);

 

         }

额~ 太晚了  今天先睡觉

2、这个算法的思想,是利用了这样一个公式.我们把ar看作是串a的转置

  (ar br)r = ba

即先把a转置 再把b转置  再把整个串转置 即得到ba

这个算法的实现是3个算法里面最容易实现的

也是最不容易错的,下面是我C的代码实现

/**********************************

       Fction:将字符串按条件转置

       char * p:字符串首地址

       int t:所要选择部分的长度

       int n:串的总长度

   Return:void

      

**********************************/

void  Q(char str[],int t,int n){

         int i ;

         char tmp;

         for(i = 0;i < t/2;i++ ){

                   tmp = str[i];

                   str[i] = str[t-1-i];

                   str[t-1-i] = tmp;

         }

         for(i = 0;i < (n-t)/2;i++ ){

                   tmp = str[t+i];

                   str[t+i] = str[n-1-i];

                   str[n-1-i] = tmp;

         }

         for(i = 0;i < n/2;i++ ){

                   tmp = str[i];

                   str[i] = str[n-1-i];

                   str[n-1-i] = tmp;

         }

}

3、这个算法被JonBentley称为杂耍.我觉得也是~不过我不是很喜欢(但JonBentley好像很推崇),

可能是我实现的不好.十分不给力.循环过多了吧.

思想就是 先开辟出来一个字的内存(这也是这个算法的优点,

至始至终就只用了这么一块内存)把要移动的第一块移动到这个内存中

然后把后续的 陆续往前移

例如:a、b、c、d、e、f

我们想把ab移到最后

先a移到那块内存中,然后c→a、e→f、那块内存的a再移到e

如果没完成那么再继续这样移动

/**********************************

       Fction:求2个数的最大公约数

       int m:操作数

       int n:操作数

Return:最大公约数

      

**********************************/

int gcd(int m,int n){

         while(n != m){

                   if(m > n)

                            m -= n;

                   if(m < n)

                            n -= m;

         }

         return n; 

}

/**********************************

       Fction:将字符串按条件转置

       char * p:字符串首地址

       int t:所要选择部分的长度

       int n:串的总长度

Return:void

      

**********************************/

void  Q(char str[],int t,int n){

         int i , j , m;

         int m = gcd(t,n);

         char tmp;

        

         for(i = 0;i < m;i++)

                   for(k = t/m;k > 0;k--){

                            tmp = str[i];

                            for(j = 0;j < (n/m-1);j++)

                                     str[j*m+i] = str[(j+1)*m+i];

                            str[j*m+i] = tmp;

                   }

}