啊哈,算法 之原语的力量

 

现在引入编程珠玑第二章第二个问题

请将一个具有n个元素的一维向量向左旋转i个位置.假如n = 8 ,i = 3 ,那么向量abcdefgh旋转之后得到的向量defghabc简单编码使用有一个具有n个元素的中间向量分n步完成此作业.你可以仅仅使用几十个字节的微小内存,花费与n成正比例的时间完成该向量的旋转?

我看到这道题目时没有看他的要求,这还不好办,申请i个辅助空间,将剩下的n-i个数向前移动,然后将辅助空间里面的数据连接上不就可以了.

作者分析到"这个方案引入了i个辅助空间,显然当数字很大的时候浪费了很多空间,而另外一个不同的方法中,我们可以定义一个函数来将x向左旋转一个位置(时间上和n成正比);然后调用n次,但这又很浪费时间"

作者提出了三中解决方法:

1 就用一个中间变量存放x[0],然后将x[i]移到x[0],x[2*i]移到x[i,依次类推(将x中的所有下标对n取摸),直到我们有回到x[0]为止,不过在这时候我们从中间变量中提取元素,然后结束该过程.如果该过程不能够移动所有的元素,那么我们从x[1]开始重复上面过程,知道所有的元素被交换到.

以下是我完成大代码,(我还没有看作者后面的原来代码,以后补上)

 

#include " stdio.h "
#include
" stdlib.h "
#include
" string.h "
#define  SIZE 10

char *  circumgyrate( char   *  number, int  circle)
{
 
int  lenChar  =  strlen (number),count  =   0  , i  =   0  , time  =   0  ;
 
char  temp ;
 
while  ( count  <  lenChar  &&  i  <=  circle  -   1 )
    {
  temp 
=  number[i];
  time 
=   0  ;
  
while  ( ((time + 1 ) * circle)  %  lenChar  !=  i  &&  count  <  lenChar )
  {
            count 
++  ;  
   number[time
* circle  %  lenChar]  =  number[(time + 1 ) * circle % lenChar];
   time 
++  ;
  }
        count 
++  ;
  number[time
* circle  % lenChar]  =  temp ;
  i 
++  ; 
 }
   
return  number ;
 
}


int  main()
{
 
char *  testChar;
 
int  number ;
 
int  circleNum ;
 printf(
" please input the number char you input: " );
 scanf(
" %d " , & number);
 testChar 
=  ( char * )malloc( sizeof ( char ) * (number + 1 ));
 printf(
" please input the chars: " );
 scanf(
" %s " ,testChar);
 printf(
" please input the number of circle you want: " );
 scanf(
" %d " , & circleNum);
    printf(
" the chars %s circle %d is: " ,testChar,circleNum);
 printf(
" %s " ,circumgyrate(testChar,circleNum));
 
return   0  ;
}

 

输出结果:

please input the number char you input:20
please input the chars:1234567890abcdefghij
please input the number of circle you want:7
the chars 1234567890abcdefghij circle 7 is:
890abcdefghij1234567

2旋转向量实际上就是将向量ab的俩个部分交换为向量ba,这里a代表前i个元素,假设a比b短,我们将b分为b1,b2,使b2的长度和a的一样长,交换b2和a,将ab1b2变化为b2b1a,现在就只要交换b2,b1的俩部分,由于新问题和原来的问题一样的,所以我们以递归的方式解决

代码(自己写的,书上的稍后补上)

 

#include " stdio.h "
#include
" stdlib.h "
#include
" string.h "

char *  reversed( char   *  number, int  frontNum , int  len, int  startLoc )
{
   
int  i ;
   
if  ( frontNum   ==  len  -  frontNum )
   {
         
for  (i  =  startLoc ; i  <  startLoc  +  frontNum; i  ++  )
   {
    number[i] 
^=  number[ i  +  frontNum];
             number[ i 
+  frontNum]  ^=  number[i];
             number[i] 
^=  number[ i  +  frontNum];
   }
   
return  number ;
   }
   
else   if  ( frontNum  <  len  -  frontNum )
   {
    
for  (  i  =  startLoc ; i  <  startLoc  +  frontNum ; i  ++  )
    {
            number[i] 
^=  number[ len  -  frontNum  +  i];
   number[len 
-  frontNum  +  i ]  ^=  number[i];
            number[i] 
^=  number[ len  -  frontNum  +  i];
    }
    
return  reversed ( number ,frontNum ,len  -  frontNum ,startLoc);
   }
   
else  
   {
         
for  ( i  =  startLoc ; i  <  startLoc  +  len  -  frontNum ; i  ++  )
   {
            number[i] 
^=  number[frontNum  +  i];
           number[frontNum 
+  i]  ^=  number[i];
            number[i] 
^=  number[frontNum  +  i];
   }
       
return  reversed ( number , 2 * frontNum  -  len ,frontNum ,startLoc  +  len  -  frontNum);
   }

}

 

int  main()
{
 
char   *  testChar ;
 
int  number ;
 
int  circleNum ;
 printf(
" please input the number char you input: " );
 scanf(
" %d " , & number);
 testChar 
=  ( char * )malloc( sizeof ( char ) * (number + 1 ));
 printf(
" please input the chars: " );
 scanf(
" %s " ,testChar);
 printf(
" please input the number of circle you want: " );
 scanf(
" %d " , & circleNum);
    printf(
" the chars %s circle %d is: " ,testChar,circleNum);
 printf(
" %s " ,reversed(testChar,circleNum,number, 0 ));
 
return   0  ;
}

 

运行结果:

please input the number char you input:20
please input the chars:1234567890abcdefghij
please input the number of circle you want:7
the chars 1234567890abcdefghij circle 7 is:
890abcdefghij1234567

3 这个算法我觉得真的是很棒的一个算法,将这个问题看做是把数组ab转换成数组ba,我们先从ab开始,转置a,然后转置b,然后将a的转置和b的转置一起转置得到ba

程序 如下(自己写的):

 

#include " stdio.h "
#include
" stdlib.h "
#include
" string.h "
char *  testChar;

void  reversed(  int  startLoc , int  endLoc)
{
 
for  (  int  i  =  startLoc ; i  <=  (endLoc  +  startLoc) / 2   && !=  endLoc  -  i  +  startLoc ; i  ++  )
 {
  testChar [i] 
^=  testChar[endLoc  -  i  +  startLoc];
  testChar[endLoc 
-  i  +  startLoc]  ^=  testChar [i] ;
  testChar [i] 
^=  testChar[endLoc  -  i  +  startLoc];
 }

}

 

int  main()
{
 
int  number ;
 
int  circleNum ;
 printf(
" please input the number char you input: " );
 scanf(
" %d " , & number);
 testChar 
=  ( char * )malloc( sizeof ( char ) * (number + 1 ));
 printf(
" please input the chars: " );
 scanf(
" %s " ,testChar);
 printf(
" please input the number of circle you want: " );
 scanf(
" %d " , & circleNum);
    printf(
" the chars %s circle %d is: " ,testChar,circleNum);
 reversed( 
0  , circleNum  -   1  ) ;
 reversed (circleNum ,number 
-   1  );
 reversed ( 
0  ,number  -   1  ) ;
 printf(
" %s " ,testChar);
 
return   0  ;
}

 

 

运行结果:

please input the number char you input:20
please input the chars:1234567890abcdefghij
please input the number of circle you want:7
the chars 1234567890abcdefghij circle 7 is:
890abcdefghij1234567

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值