- STL基本组件
- 内存相关
- 空间配置器
- 迭代器相关
- iterator,常见的五种迭代器类型(input, output, forward, bidirectional, random)
- reverse_iterator,用于容器的rbegin()/rend()操作
- iterator_traits,用于萃取迭代器中的内嵌类型定义
- 容器相关
- vector
- list
- deque,双端队列
- queue,容器适配器,由deque实现
- stack,容器适配器,由deque实现
- avl_tree,高度平衡二叉搜索树,通过旋转维持平衡
- skiplist,跳表,代替红黑树实现map和set
- map/set,由skiplist实现
- hashtable,哈希表,开链法解决冲突,必要时进行rehash
- unordered_map/unordered_set,由哈希表实现
- tuple元组
- 内存相关
- STL算法
- 不修改序列的操作
- all_of/any_of/none_of
- for_each
- count/count_of
- mismatch
- find/find_if/find_if_not
- find_end
- find_first_of
- adjacent_find
- search
- 修改序列操作
- copy/copy_if
- copy_backward
- fill
- fill_n
- generate
- generate_n
- reverse
- 排序操作
- is_sorted
- sort
- 堆操作
- is_heap
- make_heap
- push_heap
- pop_heap
- sort_heap
- 最大/最小操作
- max
- min
- 比较操作
- equal
- 排列操作
- is_permutation
- 未初始化内存上的操作
- uninitialized_copy
- uninitialized_copy_n
- uninitialized_fill
- uninitialized_fill_n
- construct
- destroy
- 不修改序列的操作
- 扩充部分
- 线程池
- 对部分算法提供了并行支持
- 支持Range
测试环境:操作系统ubuntu,编译器gcc 5.4.0,编辑器vim
//std::vector<int> vec;
tinystl::vector<int> vec;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
vec.push_back(value);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::vector | push_back | 10万 | 1.5 |
tinystl::vector | push_back | 100万 | 10 |
tinystl::vector | push_back | 1000万 | 62 |
std::vector | push_back | 10万 | 2 |
std::vector | push_back | 100万 | 12 |
std::vector | push_back | 1000万 | 72 |
//std::vector<std::string> vec;
tinystl::vector<std::string> vec;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
vec.push_back(value);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::vector<std::stirng> | push_back | 10万 | 10 |
tinystl::vector<std::stirng> | push_back | 100万 | 49 |
tinystl::vector<std::stirng> | push_back | 1000万 | 426 |
tinystl::vector<std::stirng> | push_back | 10万 | 10 |
tinystl::vector<std::stirng> | push_back | 100万 | 47 |
tinystl::vector<std::stirng> | push_back | 1000万 | 400 |
//std::string str;
tinystl::string str;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
str.push_back(value);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::string | push_back | 100万 | 7 |
tinystl::string | push_back | 1000万 | 37 |
tinystl::string | push_back | 10000万 | 217 |
std::string | push_back | 100万 | 9 |
std::string | push_back | 1000万 | 40 |
std::string | push_back | 10000万 | 260 |
unordered_set使用hashtable加开链法实现的,初始桶大小是128。在不考虑适时rehash的情况下插入大量元素会很慢,于是在每次insert之后都判断当前的负载因子,如果达到负载因子的上限,就扩大hashtable的桶大小,默认是原大小的5倍。
另外页可以考虑将rehash的时间消耗分摊到每次的insert中,参数redis
//std::unordered_set<int> ust;
tinystl::unordered_set<int> ust;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
ust.insert(i);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::unordered_set<int> | insert | 1万 | 3 |
tinystl::unordered_set<int> | insert | 10万 | 30 |
tinystl::unordered_set<int> | insert | 100万 | 150 |
std::unordered_set<int> | insert | 1万 | 3 |
std::unordered_set<int> | insert | 10万 | 15 |
std::unordered_set<int> | insert | 100万 | 77 |
//std::unordered_set<int> ust;
tinystl::unordered_set<int> ust;
int insertCnt = std::max(10000, count / 10000);
for(int i = 0; i != insertCnt; ++i)
ust.insert(i);
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
ust.count(i);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::unordered_set<int> | count | 1千万 | 95 |
tinystl::unordered_set<int> | count | 1亿 | 925 |
tinystl::unordered_set<int> | count | 10亿 | 12300 |
std::unordered_set<int> | count | 1千万 | 142 |
std::unordered_set<int> | count | 1亿 | 1415 |
std::unordered_set<int> | count | 10亿 | 15616 |
//std::priority_queue<int> pq;
tinystl::priority_queue<int> pq;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
pq.push(i);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::priority_queue<int> | push | 10万 | 10 |
tinystl::priority_queue<int> | push | 100万 | 60 |
tinystl::priority_queue<int> | push | 1000万 | 630 |
std::priority_queue<int> | push | 10万 | 7 |
std::priority_queue<int> | push | 100万 | 34 |
std::priority_queue<int> | push | 1000万 | 283 |
tinystl::vector<int> v;
for(int i = 0; i != count; ++i)
v.push_back(i);
//std::priority_queue<int> pq(v.begin(), v.end());
tinystl::priority_queue<int> pq(v.begin(), v.end());
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
pq.pop();
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::priority_queue<int> | pop | 10万 | 7 |
tinystl::priority_queue<int> | pop | 100万 | 50 |
tinystl::priority_queue<int> | pop | 1000万 | 553 |
std::priority_queue<int> | pop | 10万 | 9 |
std::priority_queue<int> | pop | 100万 | 72 |
std::priority_queue<int> | pop | 1000万 | 836 |
//std::deque<int> dq;
tinystl::deque<int> dq;
ProfilerInstance::start();
const int max = count;
for(int i = 0; i != max / 2; ++i)
dq.push_front(i);
for(int i = 0; i != max; ++i)
dq.push_back(i);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::deque<int> | push_front/back | 10万 | 2.5 |
tinystl::deque<int> | push_front/back | 100万 | 13 |
tinystl::deque<int> | push_front/back | 1000万 | 75 |
std::deque<int> | push_front/back | 10万 | 1.2 |
std::deque<int> | push_front/back | 100万 | 10 |
std::deque<int> | push_front/back | 1000万 | 40 |
//std::list<int> l;
tinystl::list<int> l;
ProfilerInstance::start();
for(int i = 0; i != count; ++i)
l.push_back(i);
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::list<int> | push_back | 10万 | 10 |
tinystl::list<int> | push_back | 100万 | 34 |
tinystl::list<int> | push_back | 1000万 | 257 |
std::list<int> | push_back | 10万 | 10 |
std::list<int> | push_back | 100万 | 36 |
std::list<int> | push_back | 1000万 | 280 |
tinystl::list中的sort最初采用归并排序,但是效率过低,于是改为快排,发现效率仍然不高。最后对快排进行优化,仅采用了插入排序优化和三数取中两种优化方法。由于是双向链表,快排比较好实现,对于单链表的快排还有待学习
tinystl::list<int> list1;
std::list<int> list2;
std::default_random_engine dre;
std::uniform_int_distribution<int> id;
for(int i = 0; i != count; ++i)
{
auto n = id(dre);
list1.push_back(n);
list2.push_back(n);
}
double cost1 = 0.0, cost2 = 0.0;
for(int i = 0; i != times; ++i)
{
ProfilerInstance::start();
list1.sort();
ProfilerInstance::finish();
cost1 += ProfilerInstance::millisecond();
ProfilerInstance::start();
list2.sort();
ProfilerInstance::finish();
cost2 += ProfilerInstance::millisecond();
}
std::cout << "tinystl::list<int>::sort time: " << cost1 << "ms" << std::endl;
std::cout << "std::list<int>::sort time: " << cost2 << "ms" << std::endl;
container | operation | 数量(个) | quantity(次) | time(ms) |
---|---|---|---|---|
tinystl::list<int> | sort | 1万 | 100万 | 60 |
tinystl::list<int> | sort | 10万 | 100 | 940 |
tinystl::list<int> | sort | 100万 | 100 | 15017 |
std::list<int> | sort | 1万 | 100 | 53 |
std::list<int> | sort | 10万 | 100 | 1240 |
std::list<int> | sort | 100万 | 100 | 34830 |
tinystl::algorithm中的sort采用快速排序实现,优化方法有较少元素时采用插入排序,三数去中,将与枢纽pivot相等的值移动到两边
std::random_device rd;
std::vector<int> v(count);
std::generate(v.begin(), v.end(), [&rd](){ return rd(); });
ProfilerInstance::start();
//std::sort(v.begin(), v.end());
tinystl::sort(v.begin(), v.end());
ProfilerInstance::finish();
ProfilerInstance::dumpDuringTime();
container | operation | quantity(次) | time(ms) |
---|---|---|---|
tinystl::algorithm | sort | 10万 | 5 |
tinystl::algorithm | sort | 100万 | 70 |
tinystl::algorithm | sort | 1000万 | 815 |
std::algorithm | sort | 10万 | 5 |
std::algorithm | sort | 100万 | 62 |
std::algorithm | sort | 1000万 | 732 |