转:编程珠玑--旋转算法
旋转算法出自《编程珠玑》第二章题目。
《编程珠玑》一书对算法是极度推崇,这点意识在我们看书的时候每每都有被灌输。使用一种好的算法往往能使得程序更加漂亮,也很能带给我们程序员某种满足感。
题目:将一个n元一维数组a[n]左移i个位置。例如,当n=8,i=3时,数组abcdefgh旋转为defghabc。请设计一个算法完成这个任务。
1. 块交换法:
分析:将n元一维数组a[n]分解为两块,将第一块存储在临时数组中,将第二块前移i个单位,再将临时数组加入到第二块后面。
如:n=8,i=3时,将第一块abc存储为临时变量,第二块defgh前移3个单位,再将abc放入到defgh后面。
思考:这种方法最大的缺陷至少需要与两块中较小的一块大小的临时变量。
2.杂技算法
分析:将a[0]存储在一个临时变量中,然后将a[i]替换a[0],a[2i]替换a[i]….当一个循环结束的时候,若替换次数小于n,则从a[1]开始替换…,需要经过gcd(n,i)(n和i的最大公约数)次循环后,才能把每一个元素都移到该移的地方。
下面是代码实现:
1 #include<iostream> 2 3 using namespace std; 4 5 //求最大公约数 6 //辗转相除法 7 int gcd(int a, int b) 8 { 9 while( a!= 0) 10 { 11 if(a>=b) a-=b; 12 else 13 { 14 int t=a; 15 a=b; 16 b=t; 17 } 18 } 19 return b; 20 } 21 22 //杂技算法 23 void Rotate1(char* a,int lenth,int rotateLen) 24 { 25 int gcdNum = gcd(lenth,rotateLen); 26 for(int i=0; i<gcdNum; i++) 27 { 28 int temp = a[i]; 29 int first = i; 30 while(1) 31 { 32 int second = (first+rotateLen)% lenth; 33 if(second == i) break; 34 a[first] = a[second]; 35 first = second; 36 } 37 a[first] = temp; 38 } 39 } 40 41 42 int main() 43 { 44 char a[9] = "abcdefgh"; 45 Rotate1(a,8,3); 46 }
3. 求逆算法
分析:将a[n]看做是向量BC组成,最终的结果需要时CB,过程如下:将BC各分别取逆B^-1C^-1,再对整个式子取逆,得到CB。
举例:将abcdefgh中的abc看做向量B,defgh看做向量C。
下面是代码实现:
1 #include<iostream> 2 3 using namespace std; 4 5 void Revert(char* str,int start,int end) 6 { 7 while(start<end) 8 { 9 char temp = str[start]; 10 str[start] = str[end]; 11 str[end] = temp; 12 start++; 13 end--; 14 } 15 } 16 17 void Rotate1(char* a,int start,int end) 18 { 19 Revert(a,0,2); 20 Revert(a,3,7); 21 Revert(a,0,7); 22 } 23 24 25 int main() 26 { 27 char a[9] = "abcdefgh"; 28 Rotate1(a,0,7); 29 }
思考题:写一个算法实现字符串反转,将abc.sina.com反转为com.sina.abc。
分析:使用求逆算法,将abc,sina,com作为子串进行反转,再将整个字符串进行反转
作者:Nick Ye(yjf512)
出处:(http://www.cnblogs.com/yjf512/)
版权声明:本文的版权归作者与博客园共有。欢迎转载阅读,转载时须注明本文的详细链接。
参考文档:
编程珠玑(第二版)