STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示

C++标准库-体系结构与内核分析

根据源代码来分析

介绍

自学C++侯捷老师的STL源码剖析的个人笔记,方便以后进行学习,查询。
为什么要学STL?按侯捷老师的话来说就是:使用一个东西,却不明白它的道理,不高明!

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第1张图片

Level 0 使用C++标准库

标准库和STL是同样的东西吗?

不是,在标准库当中百分之80左右是STL,STL分为六大部件。
一些新旧标准:

  • C++标准库没有.h的后缀了,例如#include
  • 新式的头文件不带.h,例如#include ,但是原来的带有.h的依然可以使用
  • 命名空间,把什么函数,模板之类的可以封装起来,新式的头文件以及组件都被封装到std当中

STL六大部件

  • 容器
  • 分配器
  • 算法
  • 迭代器
  • 适配器
  • 分配器
  1. 容器:容器要放东西,东西要占用内存,所以容器他非常好的是可以帮我们把内存的问题给解决掉,你看不到内存这个东西,只需要不断从容器当中放入/取出东西就好了,所以容器的背后需要另外一个部件去支持它,这个部件就是分配器,数据在容器里面。
  2. 分配器:是用来支持容器的。
  3. 算法:有一些函数/操作是由容器做的,但是更多的是包含在算法当中,操作数据的操作在算法里面。
  4. 迭代器:如何用算法去操作数据呢?使用迭代器,也就是泛化指针。
  5. 仿函数:作用像是一种函数。
  6. 适配器:把容器/算法/迭代器做一些转换。

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第2张图片

六大部件之间的关系

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第3张图片
vector>,第二个参数是allocator。
以上为六大部件之间具体的联系与配合。在上方的程序当中,less()这是标准库当中的一个仿函数,然后他的作用是进行比较,比如说a < b,然后现在利用了count_if这个算法,其作用是找到我们指定目标的数值,现在假如需要找到小于40的值,但是仿函数少了第二参数,所以就可以利用之前适配器的功能,适配器就是把容器/算法/迭代器做出一些转换,使用bind2nd这个转换,即可有了第二参数40;之后又进行函数的转换,加了一个not1,以前要找小于等于40,现在要大于40。

#include
#include
#include
#include

using namespace std;

int main(void) {
	int ia[ 6 ] = { 27, 210, 12, 47, 109, 83};
	vector<int, allocator<int>> vi(ia, ia+6);
	
	cout<< count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40)));
	return 0;
}

结果:

4

...Program finished with exit code 0
Press ENTER to exit console.

疑惑

  • 仿函数:less()这是标准库当中的一个仿函数,然后他的作用是进行比较,比如说a < b
  • 适配器
    STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第4张图片

复杂度

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第5张图片

前闭后开的区间

把元素放到容器当中,容器当然是有头有尾的,所有容器都提供begin(),end()迭代器,头没有疑虑,尾巴呢?所谓容器的前闭后开区间,标准库规定,begin()要表示开始的启动,end()表示最后一个元素的下一个元素。
STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第6张图片
###容器的遍历(C++11之前的写法):

Container<T> c;
...
Container<T>::iterator ite = c.begin();
for (; ite != c.end(); ++ite)
	...

最新的写法(最推荐C++11)基于范围的for循环

for (auto decl : coll)
{
	statement;
}

decl是一个声明,coll是一个容器,相比以前的写法,方便太多了。

不是非必要的时候不用auto,因为知道一个元素的类型还是很重要的。

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第7张图片

容器的结构

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第8张图片

容器的分类

1.序列式容器

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第9张图片

序列式容器 特点 额外学习材料
array 一段连续空间,不论是否使用,都会全部占用 array
vector 尾部可进可出,当空间不够时会自动扩充 vector
deque 双向都可扩充,两端都可进可出 deque
list 一个双向环状链表,有向前后和向后两个指针 list
forward_list 一个单向链表,仅有向后一个指针 forward_list

关联型容器

联式容器类似于key-value,非常适合于查找操作

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第10张图片

关联式容器名 特点 实现 注释 额外学习材料
set/multiset key和value是同一个,BST存储是有序的 红黑树 加上multi意味着可以重复键值对 set,multiset
map/multimap 每一个key对应一个value,BST存储是有序的 红黑树 加上multi意味着可以重复键值对 map,multimap
unordered_set/unordered_multiset 相对于set/multiset,存储是无序的 哈希表 加上multi意味着可以重复键值对 unordered_set,unordered_multiset
unordered_map/unordered_multimap 相对于map/multimap,存储是无序的 哈希表 加上multi意味着可以重复键值对 unordered_map,unordered_multimap

STL源码剖析-六大部件, 部件的关系,复杂度, 区间表示_第11张图片
在标准库当中,并没有规定set和map用什么来实现,但是用红黑树(因为左右两边会自己平衡)非常好,所以各家IDE都用红黑树来做set和map。

map,每一个节点,都有key和value,set却没有明确划分。

选择普通的set和map,里面的元素的key是不能重复的,但是使用multiset以及multimap的时候,里面的key是可以重复的。

哈希表的某一条链表不能太长,因为单链表是要不断进行遍历的,这样时间复杂度就会很高。

你可能感兴趣的:(C++,c++,算法,开发语言)