您的位置:首页 > 其它

20170407STL012_STL_容器和算法效率

2017-04-07 12:38 288 查看

效率分析:

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差别不大,但
4000
是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:我们使用的这些方法测出的不一定准,因为这些方法不一定是最优实现,比如二叉树的查找是二分法,就会非常快。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: