加速读取——三式(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;
}

希望将自己的学习经验分享给有需要的人。
我是小郑,一个坚持不懈的小白

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