《编程珠玑》第二章,三种字符串旋转算法

▶ 将长度为 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\n", 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:\n%4d->%s\n", 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\n", i, temp);
116     }
117     printf("Test spin 2:\n%4d->%s\n", 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\n", i, temp);
123     }
124 
125     printf("Test spin 3:\n%4d->%s\n", 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\n", 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\n", 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 次,记录个算法消耗的时间

猜你喜欢

转载自www.cnblogs.com/cuancuancuanhao/p/11107602.html