STL源码剖析(侯捷)笔记——STL容器的分类与测试

1、容器的结构与分类

序列式容器:元素有次序关系,包括array、vector、deque、list、forward-list(stack,queue是适配器)

关联式容器:key-value型,包括set/Multiset、map/Multimap、unordered_map/Multimap、unordered_set/Multiset.(set可看作key=value)
在这里插入图片描述

  • array:固定大小的数组
  • vector:单项扩充的向量(数组)
  • deque:双向数组,可以双端扩充
  • list:双向链表,SGI STL中源码实现为循环链表
  • forward-list:单向链表
  • set/multiset:红黑树,牺牲平衡特性的平衡二叉搜索树,插入删除速度快相比平衡二叉树,插入元素后会自动排序如set s = {4,3,2,1}; for(auto num) cout << num; 输出:1,2,3,4
  • map/multimap:同set/multiset,key-value
  • unordered_set/Multiset/unordered_map/Multimap,无序,采用哈希结构实现,如下图
  • 在这里插入图片描述

2、使用容器array

在这里插入图片描述
上图中可以学习的几个点:
获取时间戳:

clock_t timeStart = clock(); // clock()函数返回clock_t

array的一些成员函数:

size(),计算容器大小
front(),起始元素值
back(),末尾元素值
data(),数组的起始位置

qsort、qsearch函数,快速排序、二分查找,在头文件cstdlib中

//qsort源代码
void qsort(void* base, size_t num, size_t size, int(*compare)(const void*, const void*));
params:
base:要排序的容器首地址,即数组首地址
num:元素的个数,即数组中前num个元素
size:要排序的元素类型大小,如对int元素排序,则为sizeof(int)
int(*)(void*,void*):排序函数指针,自定义如:
int compareMyType (const void * a, const void * b)
{
  if ( *(MyType*)a <  *(MyType*)b ) return -1;// 先将void*转换为具体类型指针再比较,void*无法比较
  if ( *(MyType*)a == *(MyType*)b ) return 0;
  if ( *(MyType*)a >  *(MyType*)b ) return 1;
}

// qsearch源代码
void* bsearch(const void* key, const void* base, size_t num, size_t size, int(*compare)(const void*, const void*));
params:
key:指向搜索对象的指针
其余参数同qsort

3、使用容器vector

在这里插入图片描述
在这里插入图片描述
学习点:
vector的成员函数:

size():实际元素个数
data():首元素地址
capacity():vector中容量,1.52倍增长,总是大于等于size。

find算法

全局find函数std::find(),使用时函数前加::,是一个模板函数
template<class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& value)
{
	while (first != last){
		if (*first == value) return first;
		++first;
	}
	return last;
}

c++11新特性:auto关键字

类型推断, 必须有初始值
//(1)普通类型推断
auto x = 10; //推断x为int
auto y; //错误,无初始值
//(2)引用类型推断
int a = 10, &b = a;
auto c = b;// 推断出b为int&
//(3)const类型推断,有变化
const int a = 10;
auto b = a;// b推断为int,丢弃顶层const
auto &c = a;//c为const int,保留顶层const
//(4)数组和函数的推断
const char arr[] = "helloworld";
auto l = arr;//数组地址推断为指针类型,即const char*;
auto &r = arr;// r为数组引用类型,即const char(&)[];

int add(int a,int b);
auto r = add; // r推断为int(*)(int,int);
auto &r1 = add; r推断为int(&)(int,int);

auto不适用于:

  • 函数参数不能是auto类型,如int add(auto a, auto b);
  • 类的成员变量不可以是auto类型,静态成员变量可以,但是需要cosnt修饰,而且需要在类内初始化

4、使用容器list(双向链表)

list<int> c;
c.push_back(),添加元素
c.max_size(),最大容量,应该和内存容量有关。
c.sort(),list内自带sort函数,比标准库带的std::sort()更适合于list的元素排序。(当容器自带sort时,一定要用自带的)

5、使用容器forward_list(单向链表)

push_front()pop_front(),没有push_back();
forward_list<int> myList = {1,2,3};
myList.push_front(4); //myList中内容为:4,1,2,3
myList.push_front(5); //myList中内容为:5,4,1,2,3

6、slist(单链表 gnu c++非模板库内容 )

同forward_list

7、使用容器deque

在这里插入图片描述
双向队列,可以两边扩充,分段连续

dque的迭代器会将几个buffer连接起来,即++可实现移位和跳转,涉及++重载

map中每个指针指向一个buffer的首地址,buffer的大小由分配器(猜的)决定,不是固定不变的

8、使用适配器stack、queue

在这里插入图片描述
在这里插入图片描述

stack<int> st;
st.push();添加元素
st.top();获取栈顶元素
st.size();

queue<int> que;
que.size();
que.front();
que.back();
que.push();// 往末尾添加元素

9、使用容器multiset、multimap

multiset<string> c;
c.insert();// 添加元素,没有push_back,push
c.find(); 该容器自带的查找函数,比std::find()更快,后面几个关联式容器也是自带find函数

multimap<long, string> c;
c.insert(pair<long,string>(1,"hello"));// 不可用[]做索引,即不可c[i] = value;否则直接覆盖了而map可以使用索引赋值

10、使用容器unordered_multiset、unordered_multimap

在这里插入图片描述
在这里插入图片描述

unordered_multiset<string> c;
c.insert();
c.bucket_count();// 边数组的大小,比元素个数多,如果元素个数大于篮子个数,篮子会扩充,2倍左右
c.load_factor();// 装填因子,篮子中非空的个数占所有篮子的比例
c.max_load_factor();
c.max_bucket_count();

11、set、map

与multiset和multimap区别只是不可重复。

文档及视频资源github地址(非本人整理):https://github.com/ZachL1/Bilibili-plus

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值