注意了注意了注意了,重要的事情說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\n",A[1]); 49 printf("Read: %.4lf S\n",A[2]); 50 printf("Printf: %.4lf S\n",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\n",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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!