1.STL的三种类型容器
顺序容器:
vector 向量容器
deque 双端队列
list 链表
容器适配器:
stack 栈
queue 队列
priority_queue 优先级队列
关联容器:
set/multiset 集合
map/multimap 映射表
2.各容器的底层实现
具体实现请参考侯捷的《STL源码剖析》,此处不贴源码,只是对底层实现做简单介绍。
顺序容器:
<1>vector 向量容器
vector底层是动态开辟的可2倍自增长的一维数组,默认不申请空间。
第一次向vector中增加元素时,开辟一个格子,以后如果内存不足,每次扩大2倍。因此,这种数据结构在刚开始内存增长时的效率很低。vector底层内存连续。
<2>deque 双端队列容器
deque底层时动态开辟的一维可2倍自增长的二维数组,默认部申请空间。deque底层内存不连续。
第一次向deque中增加元素时,一维开辟两个格子,二维开辟的元素个数遵守以下规则:如果变量的类型<4096,开辟4096/sizeof(_Ty)个格子;否则开辟一个格子,格子大小为sizeof(_Ty)。size=sizeof(_Ty) < 4096 ? 4096/sizeof(_Ty) : sizeof(_Ty);
因为是双端队列,所以底层有两个指针(_start和_finish)。_start和_finish都向最中间。头插时,_start向上移动,尾插时,_finish向下移动。二维数组不够用时,再开辟二维空间。如果二维已经开辟满了,则一维成2倍增长(cur *= 2),并将二维空间移动到新的一维空间的最中间,减少push_front和push_back时,开辟内存和移动的次数(pos = cur/2 -1)。
<3>list
list的底层是双向链表。对list的操作就是对链表的操作,所以list容器的添加和修改效率很高。list默认分配一个头节点,在插入值的时候,动态的申请节点,挂在链表中。
容器适配器:
容器适配器底层没有自己的数据结构,他们是对某种容器的代理。
<1>stack默认的底层数据结构是deque
<2>queue默认的底层结构是queue
<3>priority_queue默认的底层结构是用vector实现的大根堆
关联容器:
关联容器的底层是RBtree,key有序排列。对关联容器的操作都是对红黑树的操作。插入元素时,最多调整2次;删除元素时,最多调整3次。
set/multiset只保存key,set中key不能重复,multiset中key可以重复
map/multimap保存的是key-value,map中key不能重复,multimap中key可以重复
Boost库中实现了hash_map和multimap,是用链地址法实现的哈希表,链表的每个元素保存的都是键值对。
3.各类型容器的操作接口函数
<1>vector
定义:vector
插入:vec.push_back(value); vec.insert(it, value);
删除:vec.erase(it); vec.erase(vec.begin(), vec.end());
获取首元素:vector::itreator it = vec.begin();
vector末尾后一个元素:vector::iterator it = vec.end();
迭代器运算:it++; it–; ++it; –it;
vector的reserver方法和resize的区别:
vec.reserver(size);//只开辟内存
vec.resize(size);//开辟空间并构建size个对象
<2>deque
定义:deque
插入:dq.push_front(value); dq.push_back(value); dq.insert(it,value);
删除:dq.erase(it); dq.erase(dq.begin(), dq.end());
获取首元素:deque::itreator it = dq.begin();
deque末尾后一个元素:deque:;iterator it = dq.end();
迭代器运算:it++; it–; ++it; –it;
<3>list
定义:list
插入:list1.push_front(value); list1.push_front(value); list1.insert(it, value);
删除:list1.erase(it); list1.erase(list1.begin(), list2.end());
切片函数:list.splice(list.begin(), list.end(), list2, list2.end());
//将list1从begin到end的节点都拼接到list2的最后面
<4>stack
定义:stack
添加元素:st.push(value);
获取栈顶元素:st.top();
删除栈顶元素:st.pop();
判断栈是否空:st.empty();
求栈的元素个数:st.size();
<5>queue
定义:queue
添加元素:qu.push(value);
获取队列首元素:qu.front();
获取队列尾元素:qu.back();
删除对头元素:qu.pop();
判断队列是否空:qu.empty();
求队列元素个数:qu.size();
<6>priority_queue
定义:priority_queue
priority_queue
添加元素:queue.push(value);
获取首元素:queue.top();
删除首元素:queue.pop();
判断队列是否空:queue.empty();
求队列的元素个数:queue.size();
<7>set/multiset
定义:set
插入:myset.insert(key);
删除:myset.erase(it); myset.erase(key);
查找:myset.find(key);
<8>map/multimap 4.泛型算法 常用泛型算法: sort(vec.begin(), vec.end()); 即:sort(vec.begin(), vec.end(), less copy(vec1.begin(), vec1.end(), back_inserter(vec2)); unique(it.begin(), it.end()); ///删除相邻重复的元素,实则是将重复的元素挪到后面,返回值是指向重复的第一个元素的迭代器 5.STL和泛型算法的实际应用 6.迭代器 迭代器的类型: 插入型迭代器的使用 <4>流迭代器
定义:map
插入:mymap.insert(makepair(key, value));
mymap[key] = value;
删除:mymap.erase(it); mymap.erase(key);
访问:map
cout
需要头文件#include
find(vec.begin(), vec.end(), value);
find_if(vec.begin(), vec.end(), bind1st(greater
sort(vec.begin(), vec.end(), greater
copy(vec1.begin(), vec1.end(), inserter(vec2, vec2.end()));#include
#include
<1>正向迭代器 iterator
<2>逆向迭代器 reserver_oterator
<3>插入型迭代器
back_insert_iterator /back_inserter push_back(value)
front_insert_iterator /front_inserter push_front(value)
isert_iterator /inserter insert(it,value)#include
istream_iterator
ostream_iterator#include