啊哈,算法 之原语的力量

 

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

请将一个具有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、付费专栏及课程。

余额充值