加速讀取——三式(getchar,std::ios::synd_with_stdio(false)、cin.tie(0))

在一些題目中會出現數據輸入很大的情況,如果我們運用不好讀取數據工具的話,那麼很可能會在讀取數據上花費較多的時間,甚至還沒讀完就超時了。

讀取速度
cin << scanf ≈ cin(關閉流同步) << getchar()


cin(關閉流同步)

爲什麼scanf的讀入數據的能力大於cin(未關閉流同步)?
C++中,cin和cout要默認與stdio同步。在cin、cout輸入輸出下,會有進行緩衝同步stdio,使scanf()與printf()能夠與cin、cout混用,也導致cin,cout語句輸入輸出緩慢。
cin關閉流的同步,就能夠實現使用cin、cout輸入輸出提速的效果(此時效果與scanf()、printf()差不多)。

std::ios::sync_with_stdio(false);

當未關閉流同步時,使用cin讀取一千萬個整數用了9.52秒。
當關閉流同步後,使用cin讀取一千萬個整數僅僅用了2.082秒。
讀取效率得到了顯著提高.

//關閉流同步
//data.txt中有一千萬個整數
#include<bits/stdc++.h>
const int MAXN = 10000000;
int numbers[MAXN];
 
int main()
{
	int start = clock();
	std::ios::sync_with_stdio(false);
    freopen("data.txt","r",stdin);
    for (int i=0;i<MAXN;i++)
        std::cin >> numbers[i];
    std::cout<<double(clock()-start)/CLOCKS_PER_SEC;
    return 0;
}

當關閉流同步利弊:
利:在輸入n6級別的數據量情況下,相對於未關閉流同步的cin,關閉流的cin輸入效率得到提高。
弊:使用scanf()和printf()、getchar()來進行輸入或輸出的話,會造成輸入、輸出混亂的情況。

進一步提升效率
在cout和cin兩者同時使用的情況下,cin與cout需要交替操作,中間會有一個flush過程,會造成時間消耗。通過 cin.tie(0) 解除cin與cout的綁定,使flush過程不再執行(注意cout沒有tie方法)。另外,使用了endl之後,會對緩衝區執行清空操作。endl會先執行’\n’,再執行flush操作,非常漫長,所以儘量使用‘\n’而不是endl執行換行。

當關閉流同步後並解除cin與cout的綁定,使用cin讀取一千萬個整數用了1.981秒。

//解除
//data.txt中有一千萬個整數
#include<bits/stdc++.h>
const int MAXN = 10000000;
int numbers[MAXN];
 
int main()
{
	std::cin.tie(0);
	int start = clock();
	std::ios::sync_with_stdio(false);
    freopen("data.txt","r",stdin);
    for (int i=0;i<MAXN;i++)
        std::cin >> numbers[i];
    std::cout<<double(clock()-start)/CLOCKS_PER_SEC;
    return 0;
}

參考文章
關於std::ios::sync_with_stdio(false)
【輸入】極速讀取


getchar()

事實上,計算機處理char類型變量的速度會快於處理int類型變量。正好可以利用這點將輸入再進行一次提速。
下面提供一個簡易的快讀模板

//快讀:讀取一個整數
//getchar讀取效率比cin、scanf要高 
int getInt()
{
	char ch = getchar();
	int x=0, f=1;
	//符號位 
	while(ch<'0' || ch>'9')
	{
		if(ch=='-') 
			f=-1;
		ch=getchar();
	}
	while('0'<=ch && ch<='9')
	{
		x = x*10+ch-'0';
		ch=getchar();
	} 
	return x*f;
}

希望將自己的學習經驗分享給有需要的人。
我是小鄭,一個堅持不懈的小白

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章