▶ 将长度为 len 的字符串旋转 dist 位的意思是:将该字符串的首字母放到该字符串末尾,重复该操作 dist 次
● 代码
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <time.h> 6 7 int gcd(int a, int b) // 求最大公约数 8 { 9 a = (a > b ? a : b); 10 b = (a > b ? b : a); 11 for(int temp = a % b;temp != 0; temp = a % b) 12 { 13 a = b; 14 b = temp; 15 } 16 return b; 17 } 18 19 int spin1(char *ss, const int len, int dist) // 跳跃下标法 20 { 21 for (int i = 0, iend = gcd(len, dist); i < iend; ++i) 22 { 23 char temp = ss[i]; 24 int oldIndex = i; 25 for (int newIndex = (oldIndex + dist) % len; newIndex != i; newIndex = (oldIndex + dist) % len) 26 { 27 ss[oldIndex] = ss[newIndex]; 28 oldIndex = newIndex; 29 } 30 ss[oldIndex] = temp; 31 } 32 return 0; 33 } 34 35 int swapTile(char *a, char *b, int tileLenght) // 交换 a 和 b 的前 tileLength 位 36 { 37 for (int i = 0; i < tileLenght; ++i) 38 { 39 char temp = a[i]; 40 a[i] = b[i]; 41 b[i] = temp; 42 } 43 return 0; 44 } 45 46 int spin2(char *ss, const int len, int dist) // 分块交换法 47 { 48 if (dist%len == 0) 49 return 0; 50 51 int i = dist, p = dist; 52 for (int j = len - dist; i != j;) 53 { 54 if (i > j) 55 { 56 swapTile(ss + p - i, ss + p, j); 57 i -= j; 58 } 59 else 60 { 61 swapTile(ss + p - i, ss + p + j - i, i); 62 j -= i; 63 } 64 } 65 swapTile(ss + p - i, ss + p, i); 66 return 0; 67 } 68 69 int spin3(char *ss, const int len, int dist) // 求逆法 70 { 71 int distR = dist % len; 72 if (distR == 0) 73 return 0; 74 for (int i = 0, j = distR - 1; i < j; ++i, --j) // 翻左手 75 { 76 char temp = ss[i]; 77 ss[i] = ss[j]; 78 ss[j] = temp; 79 } 80 for (int i = distR, j = len - 1; i < j; ++i, --j) // 翻右手 81 { 82 char temp = ss[i]; 83 ss[i] = ss[j]; 84 ss[j] = temp; 85 } 86 for (int i = 0, j = len - 1; i < j; ++i, --j) // 两手一起翻 87 { 88 char temp = ss[i]; 89 ss[i] = ss[j]; 90 ss[j] = temp; 91 } 92 return 0; 93 } 94 95 int testGcd(const int target) // 测试求最大公约数的方法 96 { 97 for (int i = 1; i <= target; ++i) 98 { 99 int temp1 = gcd(target, i), temp2 = gcd(target / temp1, i / temp1); 100 printf("(%4d,%4d) = %4d, (%4d,%4d) = %4d ", target, i, temp1, target / temp1, i / temp1, temp2); 101 } 102 return 0; 103 } 104 105 int testSpinSmall() // 测试旋转正确性 106 { 107 char origin[] = "abcdefghijklmnopqrstuvwxyz0123456789!"; 108 char temp[] = "abcdefghijklmnopqrstuvwxyz0123456789!"; 109 110 printf("Test spin 1: %4d->%s ", 0, origin); 111 for (int i = 1; i < 100; ++i) 112 { 113 strcpy(temp, origin); 114 spin1(temp, strlen(origin), i); 115 printf("%4d->%s ", i, temp); 116 } 117 printf("Test spin 2: %4d->%s ", 0, origin); 118 for (int i = 1; i < 100; ++i) 119 { 120 strcpy(temp, origin); 121 spin2(temp, strlen(origin), i); 122 printf("%4d->%s ", i, temp); 123 } 124 125 printf("Test spin 3: %4d->%s ", 0, origin); 126 for (int i = 1; i < 100; ++i) 127 { 128 strcpy(temp, origin); 129 spin3(temp, strlen(origin), i); 130 printf("%4d->%s ", i, temp); 131 } 132 return 0; 133 } 134 135 int testSpinLarge() // 测试旋转效率,对长为 size 的数组旋转指定位数 time 次 136 { 137 const int size = 10000000, time = 10; 138 char *origin = (char *)malloc(sizeof(char)*size); 139 clock_t t1, t2, tE; 140 for (int count = 1; count <= 100; count++) 141 { 142 t1 = clock(); 143 for (int i = 1; i < time; ++i) 144 spin3(origin, size, i); 145 t2 = clock(); 146 printf("%4d->%10d ms ", count, t2 - t1); 147 } 148 return 0; 149 } 150 151 int main() 152 { 153 testGcd(24); 154 testSpinSmall(); 155 testSpinLarge(); 156 getchar(); 157 return 0; 158 }
● 测试结果,在长度为 1000000 的字符串上分别旋转 1~100 位各 10 次,记录个算法消耗的时间