效率分析:
1:vector:
1:是一个连续的,有序容器
2:在尾部添加元素的效率相对比较快,但是如果需要重新分配内存的时候,就会比较慢:,如果一次分配一个比较大的空间,这样的话效率会有提高。
3:另外,如果在vector的中间或者前面添加元素的话,就会变得非常慢。
2:deque:
1:双端队列,它支持向前和向后添加。
3:list:
1:看起来,整个容器是连续的,但实际上是分开的多个块组合起来的。
2:他的所有元素都是通过指针连接起来的,插入和删除非常快,但是读取比较忙。
4:array:
1:C++11刚才添加进来的一个容器。
2:他是一个数组,他是不会变的。
容器分类:
1:序列容器:
1:array:
2:deque:
3:vector:
4:list:
5:forward_list:
2:器容器适配:
1:stack:后进先出。
2:dueue:先进先出。
3:priority_dueue:优先队列。
3:关联容器:
1:set:
2:multi_set:
3:map:
4:multi_map:
4:无序关联容器:
1:unordered_set:
2:unorder_multiset:
3:unordered_map:
4:unordered_multimap:
array效率测试:
1:array声明的时候大小就已经定下来了,他不是new出来的,所以保存在栈里面。
2:array声明在全局中,大小会相对大些。
#include <iostream>
#include <stack>
#include <array>
#include <vector>
#include <ctime>
#include <algorithm>
const unsigned int TEXTSIZE = 500000;
bool FindIf(int val)
{
return val > 10000;
}
std::array<int, TEXTSIZE> ci;//声明的时候就指定了大小,如果这个大小不合适(一般不能过大),那么运行就会报错。
void TestArray()
{
std::cout << "Array:" << std::endl;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
ci[i] = rand();
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::sort(ci.begin(), ci.end());
tend = std::clock();
std::cout << "排序的时间:" << tend - tbegin << std::endl;//排序
tbegin = std::clock();
std::count_if(ci.begin(), ci.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
void Testvector()
{
std::cout << "vector:" << std::endl;
std::vector<int> vi;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
vi.push_back(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::sort(vi.begin(), vi.end());
tend = std::clock();
std::cout << "排序的时间:" << tend - tbegin << std::endl;//排序
tbegin = std::clock();
std::count_if(vi.begin(), vi.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
int main()
{
TestArray();
std::cout << std::endl;
Testvector();
return 0;
}
3:vector涉及到动态分配。
从上面的测试结果可以看出,vector的写入时间比较长。如果提前把vector的容量扩大,然后用下标符来赋值,那么所用的时间会比较短。
4:list:
1:对list做任何的算法操作都是很慢的,对list的插入操作每次的时间都是一样的,但是对于vector等的插入,单数据量非常大的时候就会变得非常慢,list的优势就体现出来了,所以,一般情况下,我们并不使用list,数据量非常大的时候(插入等操作)才会用。
void Testlist()
{
std::cout << "list:" << std::endl;
std::list<int> li;
// vi.resize(TEXTSIZE);
// std::cout << vi.capacity() << std::endl;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
// vi[i] = rand();//这样会比push_back快6倍左右
li.push_back(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
//STL里面list不支持排序,它使用的双向迭代器。
/*tbegin = std::clock();
std::sort(li.begin(), li.end());
tend = std::clock();
std::cout << "排序的时间:" << tend - tbegin << std::endl;//排序*/
tbegin = std::clock();
std::count_if(li.begin(), li.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
2:list的访问时非常慢的。
5:forward_list:前向列表
void Testforwardlist()
{
std::cout << "forward_list:" << std::endl;
std::forward_list<int> fli;
// vi.resize(TEXTSIZE);
// std::cout << vi.capacity() << std::endl;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
// vi[i] = rand();//这样会比push_back快6倍左右
fli.push_front(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
//STL里面list不支持排序,它使用的双向迭代器。
/*tbegin = std::clock();
std::sort(li.begin(), li.end());
tend = std::clock();
std::cout << "排序的时间:" << tend - tbegin << std::endl;//排序*/
tbegin = std::clock();
std::count_if(fli.begin(), fli.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
1:不支持push_back,不支持向后插入。
2:车输出的效率比list还低些。
6:deque:队列(序列式容器)
1:排序的效率相当低。
2:在写入的时候,效率相比vector慢,
3:但是可以镶嵌添加也可以向后添加。
7:set:
1:set的插入方法非常慢,但是遍历是非常快的。
void Testset()//关联容器
{
std::cout << "set:" << std::endl;
std::set<int> fli;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
fli.insert(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(fli.begin(), fli.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
2:他里面是一个二叉树(红黑树),实际上,他在数据插入的时候就已经对数据进行排序了,,遍历里面的++算法与普通的不一样,他的效率非常高。
8:multiset:
1:multiset的效率比set要低一些,插入和遍历都会慢一些。
void Testmultiset()//与set差别不大,但是map和multimap的差别非常大。
{
std::cout << "multiset:" << std::endl;
std::multiset<int> fli;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
fli.insert(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(fli.begin(), fli.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
2:multiset用的并不多,但是multimap会用到。
9:map:涉及到键值对,以及pair对象的构造,效率比较低。
void Testmap()//与set差别不大,但是map和multimap的差别非常大。
{
std::cout << "map:" << std::endl;
std::map<int,int> mp;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
mp.insert(std::pair<int,int>(i,rand()));//这个插入会比较慢,因为每次都需要构建一个对象
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(mp.begin(), mp.end(), FindIfmap);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
10:multimap:效率也会比较低。
void Testmultimap()//与set差别不大,但是map和multimap的差别非常大。
{
std::cout << "multimap:" << std::endl;
std::multimap<int, int> mp;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
mp.insert(std::pair<int, int>(i, rand()));//这个插入会比较慢,因为每次都需要构建一个对象
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(mp.begin(), mp.end(), FindIfmap);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
11:unordered_set:
1:他的插入速度和查找速度更快。
void Testunorderedset()//关联容器
{
std::cout << "unordered_set:" << std::endl;
std::unordered_set<int> fli;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
fli.insert(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(fli.begin(), fli.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
12:unordered_multiset:
1:
void TestunorderedMultiset()//关联容器
{
std::cout << "unordered_multiset:" << std::endl;
std::unordered_multiset<int> fli;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
fli.insert(rand());
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(fli.begin(), fli.end(), FindIf);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
13:unordered_map:
1:
void TestUnorderedmap()//与set差别不大,但是map和multimap的差别非常大。
{
std::cout << "underedmap:" << std::endl;
std::unordered_map<int, int> mp;
std::clock_t tbegin = std::clock();//单位100ns
for (int i = 0; i < TEXTSIZE; ++i)
{
mp.insert(std::pair<int, int>(i, rand()));//这个插入会比较慢,因为每次都需要构建一个对象
}
std::clock_t tend = std::clock();//单位100ns
std::cout << "写入的时间:" << tend - tbegin << std::endl;//写入数据
tbegin = std::clock();
std::count_if(mp.begin(), mp.end(), FindIfmap);//这是找到第一个就退出。
tend = std::clock();
std::cout << "查找时间:" << tend - tbegin << std::endl;//查找
}
总结:
1:序列式容器里面整体效率最高的是array,然后是vector。其他的对算法来说没有帮助,只是他们的结构相对有一些优点。
2:关联容器和无序关联容器是没有push_back方法的,他们只有insert插入、erase擦除等方法。
3:map的下标运算符不是指下标,他是一个key。
4:我们使用的这些方法测出的不一定准,因为这些方法不一定是最优实现,比如二叉树的查找是二分法,就会非常快。