• 读入优化&输出优化


    注意了注意了注意了,重要的事情说3遍,这个东西是骗分神器,骗分神器,骗分神器!!!
    众所周知:scanf比cin快得多,printf比cout快得多,如果你不知道就……就现在知道了
    那有没有更快的呢?当然。
    请看:


    我懵逼了,至于慢近100ms吗? 

    好吧,这就是读入优化的效果,在数据很恐怖的情况下能比scanf多过1-5个点……
    比如说这种:

    都说了要读入优化你还不读入优化,那不是找死吗……

    前面都是废话,现在开始说正事

    读入优化

    首先,读入优化这里是只是针对整数,getchar读字符是非常快的,所以我们就用getchar了。(下面都假设输入的数为x)

    负数处理

    很简单,用一个标志变量f,开始时为1,当读入了’-’时,f变为-1,最后x*=f即可

    绝对值部分处理

    显然getchar每次只能读一位,所以,每当读了一位时x*=10,为这一位“留位置”。
    举个例子:现在读入了123,x为123,再读入了一个4,x*=10,变为了1230,现在它的最后一位空出来了,正好留给4,x+=4,x就变为了1234,当然,这里的’4’是char类型,需要减去’0’才是4,即:x=x*10+s-'0'(s为当前输入的字符)

    关于细节

    很多时候是有多余空格或者其他的乱码字符输入,为了防止bug,我们要严谨~详见代码。

    代码

     1 void read(int &x)//'&'表示引用,也就是说x是一个实参,在函数中改变了x的值就意味着在外面x的值也会被改变
     2 {
     3     int f=1;//标记正负
     4     x=0;//归零(这就是潜在bug,有可能传进来时x没有归零)
     5     char s=getchar();//读入第一个字符
     6     while(s<'0'||s>'9')//不是数字字符
     7     {
     8         if(s=='-')//不能直接把f=-1,有可能输入的不是'-'而是其他乱七八糟的东西
     9             f=-1;
    10         s=getchar();//继续读
    11     }
    12     while(s>='0'&&s<='9')//是字符(一旦不是字符就意味着输入结束了)
    13     {
    14         x=x*10+s-'0';
    15         s=getchar();
    16     }
    17     x*=f;//改变正负
    18 }

    简洁一些:

    1 void read(int &x)
    2 {
    3     int f=1;x=0;char s=getchar();
    4     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    5     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    6     x*=f;
    7 }

    这就是完整的读入优化了,你可以直接这样用:

    1 int N;
    2 read(N);

    当然还有更装逼的代码:

    1 #define num ch-'0'
    2 void get(int &res){
    3     char ch;bool flag=0;
    4     while(!isdigit(ch=getchar()))
    5         (ch=='-')&&(flag=true);
    6     for(res=num;isdigit(ch=getchar());res=res*10+num);
    7     (flag)&&(res=-res);
    8 }

    这个就真的很跳了。
    首先:isdigit是判断一个字符是否为数字字符,需要头文件#include<cctype>,刚刚忘了说,getchar需要cstdio。
    然后,那个诡异的(ch=='-')&&(flag=true)和(flag)&&(res=-res);是个什么玩意?我们发挥聪明才智,想起&&是“短路运算符”,短路运算符是啥?就是看到第一个条件错误就不会执行第二个条件,直接跳过了,所以这两句代码就不难理解了,唯一颠覆宝宝们的认知的是&&可以脱离if和return什么的直接用……

    输出优化

    如果有50%的人知道输入优化,那知道输出优化的最多不过20%,输出还能怎么优化?putchar啊!putchar是比printf快的。(下面都假设输出的数为x)
    ps:居然还有putchar这种东西?!

    负数处理

    输出就简单了,如果是负数,直接putchar('-');x=-x;即可,不解释。

    绝对值部分处理

    这里是不是还是用循环呢?答案是——否定的,为了极致的速度,我们用递归!递归什么?递归下一位啊,即x/10,然后,注意边界,x要>9才能继续递归,否则要输出x%10(因为还有最后一位)。

    关于细节

    无……

    代码

     1 void print(int x)//这里当然不用实参
     2 {
     3     if(x<0)//负数
     4     {
     5         putchar('-');
     6         x=-x;
     7     }
     8     if(x>9)//只要x还是2位数或更多就继续分解
     9         print(x/10);//这里递归完后栈里面x的每一位是倒过来的(关于递归,我也实在解释不清楚,各位去看看神犇们的递归解释吧)
    10     putchar(x%10+'0');//输出(要把int型变为char型,加'0'即可)
    11 }

    至于输出优化,目前还没发现什么太跳的,毕竟写输出优化的就少。

    对比

    为了能看出优势,我做了一个对比: 
    Test.cpp:

     1 #include<cstdio>
     2 #include<ctime>
     3 #include<windows.h>
     4 using namespace std;
     5 #define TIMES 1000000
     6 double A[5];
     7 void print(int x)
     8 {
     9     if(x<0)putchar('-'),x=-x;
    10     if(x>9)print(x/10);
    11     putchar(x%10+'0');
    12 }
    13 void read(int &x)
    14 {
    15     int f=1;x=0;char s=getchar();
    16     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    17     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    18     x*=f;
    19 }
    20 int main()
    21 {
    22     freopen("in.txt","r",stdin);
    23     freopen("111.txt","w",stdout);
    24     int a;
    25     double t1,t2;
    26     t1=clock();
    27     for(int i=1;i<=TIMES;i++)
    28         scanf("%d",&a);
    29     t2=clock();
    30     A[1]=(t2-t1)/1000;
    31     t1=clock();
    32     for(int i=1;i<=TIMES;i++)
    33         read(a);
    34     t2=clock();
    35     A[2]=(t2-t1)/1000;
    36     t1=clock();
    37     for(int i=1;i<=TIMES;i++)
    38         printf("%d",a);
    39     t2=clock();
    40     A[3]=(t2-t1)/1000;
    41     t1=clock();
    42     for(int i=1;i<=TIMES;i++)
    43         print(a);
    44     t2=clock();
    45     A[4]=(t2-t1)/1000;
    46     fclose(stdout);//为了不输出前面一堆东西
    47     freopen("out.txt","w",stdout);
    48     printf("Scanf:  %.4lf S
    ",A[1]);
    49     printf("Read:   %.4lf S
    ",A[2]);
    50     printf("Printf: %.4lf S
    ",A[3]);
    51     printf("Print:  %.4lf S",A[4]);
    52 }

    Data.cpp:

     1 #include<cstdio>
     2 #include<ctime>
     3 #include<cstdlib>
     4 #define TIMES 1000000
     5 #define MAXN 100000
     6 int main()
     7 {
     8     srand(time(NULL));
     9     freopen("in.txt","w",stdout);
    10     for(int i=1;i<=TIMES*2;i++)
    11     {
    12         if(rand()%2)
    13             printf("-");
    14         printf("%d
    ",rand()%MAXN);
    15     }
    16 }

    如果你想测cin,cout,自己试试吧…… 
    以下是我的测试结果(测5次,数据一模一样):

    次数        scanf耗时              read耗时                 printf耗时              print耗时
    1             0.2960 S                0.0790 S                0.1870 S               0.0630 S
    2             0.2960 S                0.0940 S                0.1720 S               0.0630 S
    3             0.2810 S                0.0780 S                0.1870 S               0.0630 S
    4             0.2960 S                0.0790 S                0.1870 S               0.0470 S
    5             0.2970 S                0.0780 S                0.1720 S               0.0630 S


    这里用了1000000组数据,输入优化比scanf快了约0.2秒,也就是说,每50万组数据读入优化要快0.1秒(100ms),刚好符合了最开始的数据范围。



    作者:∞∑
    来源:CSDN
    原文:https://blog.csdn.net/c20190102/article/details/69710341
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    第5章 构建Spring Web应用程序
    第4章 面向切面的Spring
    第3章 高级装配
    js json和字符串的互转
    webservice CXF入门服务端
    javascript的解析执行顺序
    java AES加密解密
    redis学习 java redis应用
    项目部署操作linux数据库mysql出现表找不到
    灯具板SOP
  • 原文地址:https://www.cnblogs.com/jiamian/p/11184179.html
Copyright © 2020-2023  润新知