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


    ▶ 将长度为 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 次,记录个算法消耗的时间

  • 相关阅读:
    多列转两列(Power Query)
    多簿多表合并(Power Query)
    高亮显示指定内容
    价格段公式
    按日期段计算平均销量
    Filter、Unique如何跳过隐藏行
    人民币填空
    按换行符拆分(Power Query)
    添加分类汇总小计行(Power Query)
    添加累计列(Power Query)
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/11107602.html
Copyright © 2020-2023  润新知