今天遇到一个问题,在与同事讨论问题的时候,提到vector的push_back是否很快的时候。自己不假思索的认为,如果没有随机读的需求的话,换成链表的方式,会有更快的插入效率。但只是根据一些经验性的做出判断。原因如下:list每插入一个节点,是O(1)的时间复杂度,不需要其他什么操作。而vector如果插入的话,则需要重复分配内存,需要更大空间,这必然很耗时的操作,所以认为list的push_back效率比vector更快。
但自己心里还是没什么底,好吧,写个测试代码试一下,看一下结果如何。
#include <vector>
#include <list>
using namespace std;
long getCurrentTime()
{
struct timeval tv;
gettimeofday(&tv,NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
const int MAX_TIMES = 10000;
int main(int argc, char ** argv) {
list<int> l_tmp;
vector<int> v_tmp;
long tickStart = getCurrentTime();
cout<<"tickStart = "<<tickStart<<endl;
for (int i = 0; i < MAX_TIMES; ++i) {
v_tmp.push_back(i);
}
long tickEnd = getCurrentTime();
cout << "tickEnd = " << tickEnd << endl;
cout << "time takes = " << tickEnd - tickStart << endl;
tickStart = getCurrentTime();
for (int i = 0; i < MAX_TIMES; ++i) {
l_tmp.push_front(i);
}
tickEnd = getCurrentTime();
cout << "tickEnd = " << tickEnd << endl;
cout << "time takes = " << tickEnd - tickStart << endl;
cout << "hello " << endl;
return 0;
}
测试机器是自己的一台mac air。
测试结果分三组数据,分别插入10万,100万,1000万,
测试结果分别为:
vector | list | |
10万 | 4 | 15 |
100万 | 32 | 139 |
1000万 | 300 | 1297 |
测试结果让自己惊讶,与预期完全相反。。在windows机器上做了一遍测试,结果也是一样。
分析:
1、vector的push_back虽然在内存不足的时候会重新申请内存,但它申请内存是预先申请原来多一倍的空间,所以很多时候均是直接往内存里面写数据即可,效率非常高。
2、list的push_back,虽然是增加一个节点。但每个新增节点的时候,都是new了一块新内存出来,再连到链表上去。new这个操作是非常吃内存的。
综上两个原因,如果在大量尾部插入的情况下,vector的push_back效率还是要高于list的push_back的。不要被自己的经验所困住,多动手实践才是王道。