编程珠玑读书笔记——串的转置算法

将一个具有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(这里假设ab)

                   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好像很推崇),

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

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

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

然后把后续的 陆续往前移

例如:abcdef

我们想把ab移到最后

a移到那块内存中,然后caef、那块内存的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;

                   }

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值