侯捷STL学习(一)--顺序容器测试
- 开始跟着《STL源码剖析》的作者侯捷真人视频,学习STL,了解STL背后的真实故事!
- 视频链接:侯捷STL
- 还有很大其他视频需要的留言
第一节:STL版本和重要资源
- STL和标准库的区别

第二节:STL六大部件
- 迭代器将容器和算法结合起来
- 分配器实现,适配器用的地方很多

- 实例:

- 理解容器的前闭后开的设计。迭代器类似于指针,很多操作和指针差不多++,--运算。vec.begin(),vec.end()指向容器最后一个元素的下一个位置,解引用*(vec.end())错误!
- auto关键字的应用
std::vector<double> vec;
for(auto elem: vec)
{
std::cout<<elem<<std::endl;
}
第三节:容器之分类和各种测试(一)
分类结构
- 红色框中标注的是C++11开始有的容器
- Array数组容器,大小固定的
- Deque:两段都可以进行插入删除操作,但是从内存上讲不通,怎么实现的要从后面的学习知道。
- List:是一个双向的循环链表,注意是双向的。
- Forward-List:单向链表,当能用单向链表的时候尽量用,可以减少内存空间,一个指针在32位pc上占4个字节,当数据量很多上百万,不可忽略!
- Set键值都一样,MultiSet允许元素有重复。
- Set/Map用红黑树实现,RB-tree是自平衡的二叉树。
- Unorder Containers:是C++标准库里卖的内容。
- 根据这些图例,可以知道这些容器在内存用到的数据结构是什么样的。
- HashTable实现方法很多,但基本都用Separate Chaining(分离链地址法实现)。

测试Array
- 指针
void* a->*(long*)a; array<long, size> c使用初始化大小,#include<array>c.data()返回这个数组的初始地址,和数组的地址对比- qsort应用:
qsort(c.data,size,size(long),comparelongs) - bsearch()应用,查找前必须排好序了:
bsearch(&target,(c.data()),size,size(long),comparelongs) - qsort,bsearch包含头文件
#include<cstdlib>,C本身库函数
#include <array>
#include <iostream>
#include <ctime>
#include <cstdlib> //qsort, bsearch, NULL
namespace jj01
{
void test_array()
{
cout << "\ntest_array().......... \n";
array<long,ASIZE> c;
clock_t timeStart = clock();
for(long i=0; i< ASIZE; ++i) {
c[i] = rand();
}
cout << "milli-seconds : " << (clock()-timeStart) << endl; //
cout << "array.size()= " << c.size() << endl;
cout << "array.front()= " << c.front() << endl;
cout << "array.back()= " << c.back() << endl;
cout << "array.data()= " << c.data() << endl;
long target = get_a_target_long();
timeStart = clock();
::qsort(c.data(), ASIZE, sizeof(long), compareLongs);
long* pItem = (long*)::bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs);
cout << "qsort()+bsearch(), milli-seconds : " << (clock()-timeStart) << endl; //
if (pItem != NULL)
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
}
}
第四节:容器之分类和各种测试(二)
测试Vector
- 主要通过程序细节说明
namespace命名空间的说明vector的增长速度是2倍增长,当capacity不够时,容量增长为前面的2倍。是在另外的2倍空间!try...catch...捕获函数,字符串最大占一个指针大小,空间不够的时候抛出,abort()退出::find()模板函数,加冒号表明是全局函数,当没有冒号时,编译器在当前没有找到,也会到全局去找。- 用两种查找算法比较,find()用时更少。
#include <vector>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort() //qsort, bsearch, NULL
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
#include <algorithm> //sort()
namespace jj02
{
void test_vector(long& value)
{
cout << "\ntest_vector().......... \n";
vector<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
//曾經最高 i=58389486 then std::bad_alloc
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "vector.max_size()= " << c.max_size() << endl; //1073747823
cout << "vector.size()= " << c.size() << endl;
cout << "vector.front()= " << c.front() << endl;
cout << "vector.back()= " << c.back() << endl;
cout << "vector.data()= " << c.data() << endl;
cout << "vector.capacity()= " << c.capacity() << endl << endl;
string target = get_a_target_string();
{
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);
cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl << endl;
else
cout << "not found! " << endl << endl;
}
{
timeStart = clock();
sort(c.begin(), c.end());
cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl;
timeStart = clock();
string* pItem = (string*)::bsearch(&target, (c.data()),
c.size(), sizeof(string), compareStrings);
cout << "bsearch(), milli-seconds : " << (clock()-timeStart) << endl;
if (pItem != NULL)
cout << "found, " << *pItem << endl << endl;
else
cout << "not found! " << endl << endl;
}
c.clear();
test_moveable(vector<MyString>(),vector<MyStrNoMove>(), value);
}
}
第五节:容器之分类和各种测试(三)
测试List,双向链表
list.max_size()按理list是动态申请空间的,为什么最大的size呢?list双向链表实现- 有趣的
c.sort(),这里注意在STL标准库全局有一个sort函数,但这里调用的是list容器自身内部的sort函数。注意在STL容器中有些自身有sort函数,此时用自身的排序算法更快。
#include <list>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <algorithm> //find()
#include <iostream>
#include <ctime>
namespace jj03
{
void test_list(long& value)
{
cout << "\ntest_list().......... \n";
list<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "list.size()= " << c.size() << endl;
cout << "list.max_size()= " << c.max_size() << endl; //357913941
cout << "list.front()= " << c.front() << endl;
cout << "list.back()= " << c.back() << endl;
string target = get_a_target_string();
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);
cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
timeStart = clock();
c.sort();
cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;
c.clear();
test_moveable(list<MyString>(),list<MyStrNoMove>(), value);
}
}
测试forward-list,单向链表
forward-list单向链表,C++11出现的push_front在链表头插入,不提供在尾部插入,效率低些。front取链表头的元素,不提供back()操作取链表尾的元素。c.sort()用它自身的排序算法
#include <forward_list>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj04
{
void test_forward_list(long& value)
{
cout << "\ntest_forward_list().......... \n";
forward_list<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_front(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "forward_list.max_size()= " << c.max_size() << endl; //536870911
cout << "forward_list.front()= " << c.front() << endl;
string target = get_a_target_string();
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);
cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
timeStart = clock();
c.sort();
cout << "c.sort(), milli-seconds : " << (clock()-timeStart) << endl;
c.clear();
}
}
测试slist
Gnu C之前的单链表,forward-list是C++11才出现的#include<ext\slist>头文件
#include <ext\slist>
//注意, 上一行並沒有引發警告訊息如 #include <ext\hash_set> 所引發者:
//...\4.9.2\include\c++\backward\backward_warning.h
//[Warning] ...
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj10
{
void test_slist(long& value)
{
cout << "\ntest_slist().......... \n";
__gnu_cxx::slist<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_front(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
}
}
测试deque
- 双向开口,是分段连续,感觉是连续的,其实不是。
- 内存上两边都可以扩充
- 每次
512扩充,两边扩充申请buffer,buffer由指针指向 max_size由限制,使用全局的sort排序

#include <deque>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj05
{
void test_deque(long& value)
{
cout << "\ntest_deque().......... \n";
deque<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "deque.size()= " << c.size() << endl;
cout << "deque.front()= " << c.front() << endl;
cout << "deque.back()= " << c.back() << endl;
cout << "deque.max_size()= " << c.max_size() << endl; //1073741821
string target = get_a_target_string();
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target);
cout << "std::find(), milli-seconds : " << (clock()-timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
timeStart = clock();
sort(c.begin(), c.end());
cout << "sort(), milli-seconds : " << (clock()-timeStart) << endl;
c.clear();
test_moveable(deque<MyString>(),deque<MyStrNoMove>(), value);
}
}
测试stack
- 栈,数据结构上和deque差不多
- 两段插入插入删除受限的容器
- 也有人叫做容器的适配器adapter
- 没有提供容器的迭代器iterator,否则对迭代器的操作会破坏堆栈的结构
- 也没有提供find,sort的功能;但是有时候让你实现堆栈的排序操作

#include <stack>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj17
{
void test_stack(long& value)
{
cout << "\ntest_stack().......... \n";
stack<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
{
stack<string, list<string>> c; //以 list 為底層
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
}
{
stack<string, vector<string>> c; //以 vector 為底層
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
}
{
stack<string, set<string>> c; //以 set 為底層
/*!
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
c.pop();
cout << "stack.size()= " << c.size() << endl;
cout << "stack.top()= " << c.top() << endl;
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_back'
*/
}
//!stack<string, map(string>> c5; ////以 map 為底層, [Error] template argument 2 is invalid
//!stack<string>::iterator ite1; //[Error] 'iterator' is not a member of 'std::stack<std::basic_string<char> >'
}
}
测试queue
- 堆,数据结构上有deque衍生出来的
- 没有提供容器的迭代器iterator,否则对迭代器的操作会破坏堆栈的结构

#include <queue>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj18
{
void test_queue(long& value)
{
cout << "\ntest_queue().......... \n";
queue<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
c.pop();
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
{
queue<string, list<string>> c; //以 list 為底層
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
c.pop();
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
}
{
queue<string, vector<string>> c; //以 vector 為底層
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
//!c.pop(); //[Error] 'class std::vector<std::basic_string<char> >' has no member named 'pop_front'
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
}
{
queue<string, set<string>> c; //以 set 為底層
/*!
for(long i=0; i< 10; ++i) {
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
c.pop();
cout << "queue.size()= " << c.size() << endl;
cout << "queue.front()= " << c.front() << endl;
cout << "queue.back()= " << c.back() << endl;
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'front'
//[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_front'
*/
}
//! queue<string, map<string>> c5; //以 map 為底層, [Error] template argument 2 is invalid
//! queue<string>::iterator ite1; //[Error] 'iterator' is not a member of 'std::queue<std::basic_string<char> >'
}
}
侯捷STL学习(一)--顺序容器测试的更多相关文章
- 侯捷STL学习(二)--序列容器测试
第六节:容器之分类和各种测试(四) stack不提供iterator操作,破坏了容器的独特性,先进先出. 使用容器multiset(允许元素重复) 内部是红黑树,insert操作就保证了排好了序. 标 ...
- 侯捷STL学习(十)--容器hashtable探索(unordered set/map)
layout: post title: 侯捷STL学习(十) date: 2017-07-23 tag: 侯捷STL --- 第二十三节 容器hashtable探索 hashtable冲突(碰撞)处理 ...
- 侯捷STL学习(九)--关联式容器(Rb_tree,set,map)
layout: post title: 侯捷STL学习(九) date: 2017-07-21 tag: 侯捷STL --- 第十九节 容器rb_tree Red-Black tree是自平衡二叉搜索 ...
- 侯捷STL学习(12)--STL相关内容hash+tuple
layout: post title: 侯捷STL学习(12) date: 2017-08-01 tag: 侯捷STL --- 第四讲 STL相关的内容 Hash Function 将hash函数封装 ...
- 侯捷STL学习(11)--算仿+仿函数+适配器
layout: post title: 侯捷STL学习(十一) date: 2017-07-24 tag: 侯捷STL --- 第三讲 标准库内核分析-算法 标准库算法形式 iterator分类 不同 ...
- 侯捷STL学习(八)-- 深度探索deque
layout: post title: 侯捷STL学习(八) date: 2017-07-19 tag: 侯捷STL --- 第十八节 深度探索deque上 duque内存结构 分段连续,用户看起来是 ...
- 侯捷STL学习(七)--深度探索vector&&array
layout: post title: 侯捷STL学习(七) date: 2017-06-13 tag: 侯捷STL --- 第十六节 深度探索vector vector源码剖析 vector内存2倍 ...
- 侯捷STL学习(一)
开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...
- 侯捷STL学习(二)
第六节:容器之分类和各种测试(四) stack不提供iterator操作,破坏了容器的独特性,先进先出. 使用容器multiset(允许元素重复) 内部是红黑树,insert操作就保证了排好了序. 标 ...
随机推荐
- 【bzoj5085】最大(二分+乱搞)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5085 这道题我们可以先二分答案,然后转化为判定是否有四角权值>=mid的矩形. ...
- EntityFramework 学习 一 Colored Entity in Entity Framework 5.0
You can change the color of an entity in the designer so that it would be easy to see related groups ...
- js正则表达式验证(化繁为简)
以前用js写正则表达式验证,每一个文本框后面都要添加一个onblur函数,验证的信息少,也没体会到有多繁琐,这次项目中的页面比较多,页面中的信息也比较多,如果每个文本框都加一个验证函数的话,js验证代 ...
- DataX-ElasticSearch(写)
DataX写入ElasticSearch 1 快速介绍 数据导入elasticsearch的插件 2 实现原理 使用elasticsearch的rest api接口, 批量把从reader读入的数据写 ...
- JavaWeb -- 文件上传下载示例
1. 上传简单示例 Jsp <%@ page language="java" import="java.util.*" pageEncoding=&quo ...
- OpenStack企业私有云新需求(1):Nova 虚机支持 GPU
作者:Sammy Liu 刘世民 本系列会介绍OpenStack 企业私有云的几个需求: GPU 支持 自动扩展(Auto-scaling)支持 混合云(Hybrid cloud)支持 物理机(Bar ...
- Nginx虚拟主机配置模板
/////////////////////////////写在前头//////////////////////////////////////////Nginx 服务器中文文档:http://www. ...
- css3+jquery+js做的翻翻乐小游戏
主要是为了练习一下css3的3D翻转功能,就做了这么个小游戏,做的比较粗糙,但是效果看的见. 主要用到的css3代码如下: html结构: <div class="container& ...
- hdu3605最大流
题意:给n个人m个星球,每个人适不适合去某个星球,每个星球的最大容量,看能不能满足所有人能去一个星球 题解:可以看出如果直接建边,边的个数是1e5左右的,这样时间肯定会爆掉,那么我们考虑用二进制状态压 ...
- PCA算法详解——本质上就是投影后使得数据尽可能分散(方差最大),PCA可以被定义为数据在低维线性空间上的正交投影,这个线性空间被称为主⼦空间(principal subspace),使得投影数据的⽅差被最⼤化(Hotelling, 1933),即最大方差理论。
PCA PCA(Principal Component Analysis,主成分分析)是一种常用的数据分析方法.PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量 ...