STL中vector用比较,list由于习惯原因基本没用,最近看了下list的用法,发现和vector用法基本相同,只是list示支持按下标索引元素,需要枚举器访问。
下面是经常说到vector和list的两种区域
vector
会自动增长的数组,内部是对数组的封装,最大的优势就是随机访问的能力,但是前端和中间对数据进行操作必然会引起数据块的移动, 这对性能影响是非常大的。
list
一个双向链表的实现,为了提供双向遍历的能力,list要比一般的数据单元多出两个指向前后的指针,list数据是链式存储,所以不能随机存取元素,它的优势在于任意位置添加 删除元素的速度。
问题
从上面简单描述,vector随机访问速度快,list插入和删除操作速度快。
但究竟什么情况用vector什么情况下用list(list按下标访问不是事,随便写个封装就行)呢?下面作一个简单实验探究,看看两者实际的访问、插入、删除、查询速度。
(ps: 笔者平时只用vector,没细究过两者差别,这里算补交一下作业~)
这里先上代码,先说一下代码并不完全自己写,而在另一篇博主的代码基础上改的(现在真的是有点太懒了),但两个测试时间是完全自己写的。
代码原博客网址:https://blog.csdn.net/zhouzhenhe2008/article/details/77428743/
下面修改后的代码与实验性能的代码
主要代码
typedef struct info_s
{
int nNumber;
int arr[100]; //性能主测试点,对vecotr来说大小不同会带来移动时拷贝的性能不同
bool operator==(struct info_s b) const
{
return this->nNumber == b.nNumber;
}
bool operator!=(struct info_s b) const
{
return this->nNumber != b.nNumber;
}
bool operator>=(struct info_s b) const
{
return this->nNumber >= b.nNumber;
}
bool operator<=(struct info_s b) const
{
return this->nNumber <= b.nNumber;
}
bool operator>(struct info_s b) const
{
return this->nNumber > b.nNumber;
}
bool operator<(struct info_s b) const
{
return this->nNumber < b.nNumber;
}
}info_t;
#include "stdafx.h"
#include "VecotrListTest.h"
#include "OrangeTimeTest.h"
using namespace OrangeUtilities;
typedef std::list< info_t > list_t;
typedef std::vector< info_t > vector_t;
void append(list_t &List, info_t &info)
{
//std::cout << "***append****" << std::endl;
List.push_back(info);
}
void append(vector_t &List, info_t &info)
{
//std::cout << "***append****" << std::endl;
List.push_back(info);
}
void for_each(list_t &List)
{
std::cout << "***for_each****" << std::endl;
list_t::iterator iter;
for (iter = List.begin(); iter != List.end(); iter++)
{
std::cout << iter->nNumber << std::endl;
}
}
void del_end_info(list_t &List)
{
std::cout << "***del_end_info****" << std::endl;
if (!List.empty())
{
List.pop_back();
}
}
void for_each_delete(list_t &List)
{
list_t::iterator iter;
for (iter = List.begin(); iter != List.end();)
{
std::cout << "delete before iter->number:" << iter->nNumber << std::endl;
iter = List.erase(iter);
std::cout << "delete after iter->number:" << iter->nNumber << std::endl;
}
}
int insert_one(list_t &List, info_t &info, int iPlace)
{
int i = 0;
std::cout << "insert_one" << std::endl;
if (iPlace < 0)
{
std::cout << "insert_one param error" << std::endl;
return -1;
}
list_t::iterator iter = List.begin();
while (iter != List.end())
{
//std::cout<<" dump "<< (*iVector)<nNumber << std::endl;
return 0;
}
i++;
++iter;
}
iter = List.insert(List.end(), info);
return 0;
}
int insert_one(vector_t &List, info_t &info, int iPlace)
{
int i = 0;
std::cout << "insert_one" << std::endl;
if (iPlace < 0)
{
std::cout << "insert_one param error" << std::endl;
return -1;
}
vector_t::iterator iter = List.begin();
while (iter != List.end())
{
//std::cout<<" dump "<< (*iVector)<nNumber << std::endl;
return 0;
}
i++;
++iter;
}
iter = List.insert(List.end(), info);
return 0;
}
void find_one(list_t &List, info_t info)
{
std::cout << "find_one" << std::endl;
list_t::iterator iter;
iter = std::find(List.begin(), List.end(), info);
if (iter != List.end())
{
//std::cout << "find it" << std::endl;
}
else
{
//std::cout << "not find it" << std::endl;
}
}
void find_one(vector_t &List, info_t info)
{
std::cout << "find_one" << std::endl;
vector_t::iterator iter;
iter = std::find(List.begin(), List.end(), info);
if (iter != List.end())
{
//std::cout << "find it" << std::endl;
}
else
{
//std::cout << "not find it" << std::endl;
}
}
void Sort(list_t & List)
{
std::cout << "Sort it" << std::endl;
List.sort();
for_each(List);
}
info_t ListAt(list_t &l, int index)
{
list_t::iterator iter = l.begin();
advance(iter, l.size()/2);
info_t info;
info.nNumber = iter->nNumber;
return info;
}
info_t ListAt(vector_t &l, int index)
{
vector_t::iterator iter = l.begin();
advance(iter, l.size() / 2);
info_t info;
info.nNumber = iter->nNumber;
return info;
}
void InsertAt(list_t &l, info_t &info, int index)
{
list_t::iterator iter = l.begin();
advance(iter, index);
l.insert(iter, info);
}
void InsertAt(vector_t &l, info_t &info, int index)
{
vector_t::iterator iter = l.begin();
advance(iter, index);
l.insert(iter, info);
}
void DeleteAt(list_t &l, int index)
{
list_t::iterator iter = l.begin();
advance(iter, index);
l.erase(iter);
}
void DeleteAt(vector_t &l, int index)
{
vector_t::iterator iter = l.begin();
advance(iter, index);
l.erase(iter);
}
void TestList()
{
list_t infoList;
info_t info;
int s = sizeof(info);
memset(&info, 0, sizeof(info_t));
int n = 1024 * 1024;
TimeTest t;
t.BeginCounter();
for (int i = 0; i < n; i++)
{
info.nNumber = i;
infoList.push_back(info);
}
int msec = t.EndCounter();
std::cout << "Inser 1M data, time is " << msec << " ms" << std::endl;
t.BeginCounter();
info_t temp = ListAt(infoList, n / 2);
std::cout << "The middel data[n/2] is " << temp.nNumber << std::endl;
msec = t.EndCounter();
std::cout << "access middle data, time is " << msec << " ms" << std::endl;
t.BeginCounter();
find_one(infoList, temp);
std::cout << "find middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
insert_one(infoList, temp, n / 2);
std::cout << "insert in middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
InsertAt(infoList, temp, n / 2);
std::cout << "insert at in middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
infoList.push_back(temp);
std::cout << "push back data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
DeleteAt(infoList, n / 2);
std::cout << "delete data at middel, time is " << t.EndCounter() << " ms" << std::endl;
}
void TestVecotr()
{
vector_t infoList;
info_t info;
int s = sizeof(info);
memset(&info, 0, sizeof(info_t));
int n = 1024 * 1024;
TimeTest t;
t.BeginCounter();
for (int i = 0; i < n; i++)
{
info.nNumber = i;
infoList.push_back(info);
}
int msec = t.EndCounter();
std::cout << "Inser 1M data, time is " << msec << " ms" << std::endl;
t.BeginCounter();
info_t temp = ListAt(infoList, n / 2);
std::cout << "The middel data[n/2] is " << temp.nNumber << std::endl;
msec = t.EndCounter();
std::cout << "access middle data, time is " << msec << " ms" << std::endl;
t.BeginCounter();
find_one(infoList, temp);
std::cout << "find middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
insert_one(infoList, temp, n / 2);
std::cout << "insert in middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
InsertAt(infoList, temp, n / 2);
std::cout << "insert at in middle data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
infoList.push_back(temp);
std::cout << "push back data, time is " << t.EndCounter() << " ms" << std::endl;
t.BeginCounter();
temp.nNumber = 999;
DeleteAt(infoList, n / 2);
std::cout << "delete data at middel, time is " << t.EndCounter() << " ms" << std::endl;
}
int main()
{
TestList();
std::cout << "-------------------------" << std::endl;
TestVecotr();
getchar();
return 0;
}
先简要介绍一下上面测试:
info_t 大小由int arr[100]决定,测试中分别100个元素和1000个元素作了测试,而list和vector大小则采集1M个元素作测试
arr[100] n=1M测试结果
Inser 1M data, time is 2451 ms
The middel data[n/2] is 524288
access middle data, time is 90 ms
find_one
find middle data, time is 169 ms
insert_one
insert in middle data, time is 413 ms
insert at in middle data, time is 89 ms
push back data, time is 0 ms
delete data at middel, time is 89 ms
Inser 1M data, time is 1937 ms
The middel data[n/2] is 524288
access middle data, time is 0 ms
find_one
find middle data, time is 37 ms
insert_one
insert in middle data, time is 372 ms
insert at in middle data, time is 27 ms
push back data, time is 0 ms
delete data at middel, time is 30 ms
arr[1000] n=1M测试结果
Inser 1M data, time is 3950 ms
The middel data[n / 2] is 524288
access middle data, time is 101 ms
find_one
find middle data, time is 219 ms
insert_one
insert in middle data, time is 423 ms
insert at in middle data, time is 99 ms
push back data, time is 0 ms
delete data at middel, time is 99 ms
Inser 1M data, time is 8565 ms
The middel data[n / 2] is 524288
access middle data, time is 0 ms
find_one
find middle data, time is 110 ms
insert_one
insert in middle data, time is 658 ms
insert at in middle data, time is 272 ms
push back data, time is 0 ms
delete data at middel, time is 280 ms
由上面的结果分析:
list在访问元素、插入、删除等操作耗时基本相同,并且在400MB数据和4000MB数据访问元素、插入、删除操作耗时没有太大变化
vector的元素访问速度非常快,基本可以忽略不计,在400MB数据下的插入、删除操作要优于list,但在4000MB速度下性能变差不如list
结论
小M没作更详细的研究实验,只能粗略的得出结论:
如果只需要访问和修改数据,不进行频繁的插入、删除等操作,那么用vector
如果数据变非常大(如上GB),并且需要频繁的插入、删除操作,那么用list
对于小型项目,数据量不大(100M以内)vector各方面比list性能要好。
实验条件
OS: Windows 10 x64
内存:12GB
CPU: Intel Core I7-4700HQ
程序:64位
结束分割线-------------------------------------------------------------------------------------------
本次实验只在400MB和4000MB数据下进行了测试,没有连续性测试,只能得出粗略的结论,如有不当之处请各位路过的朋友不吝指正,大家一起进步