1.容器介绍
(1)容器Container简介
1)序列式容器:arrar/vector/deque/list/forwad_list
底层原理:数据组或指针
介绍:元素是线性存储的,可以通过迭代器顺序访问
2)关联式容器: set/map/mutiset/multimap
底层原理:二叉树、红黑树 ,时间复杂第最高log N
(补充:兼容性比较差的有hash_map、hash_set)
介绍:底层实现都是红黑树,默认情况下升序排列,不能修改关键字的值,支持双向访
问迭代器
3)无顺序容器 unordered_map/unordered_set/unordered_multimap/unordered_multiset
底层原理:哈希表
介绍:底层实现都是哈希表,查找时间复杂度O(1),存放元素是无序的,对于自定
义类型必须给出哈希函数,支持前向访问迭代器
4)补充:
此外还有: stack / queue / priority_queue / string / bitset (通常bool类型只有一个字节,处理位集合更容易一些)
(2)容器的基本知识
1)必须可以复制(copy)或者搬移(move)(隐含的条件是在拷贝和搬移的过程中没有副作用)
这个图片中每次搬移都要打印一句话,就是副作用的例子
2)可以被复制或搬移的例子: bool char int double pointer
3)不可以被搬移或复制的例子:reference function
4 ) 必须可以被赋值来操作赋值或搬移
5)元素可以被销毁的细节
针对不同容器还有特殊的要求
①对于序列式容器,元素必须有默认的构造函数
②对于某些操作,元素需要定于 == std::find
③对于关联式容器,排序默认的是std::less
④无顺序容器,必须要提供一个hash函数 ==
⑤stl容器里面存的是元素的值而不是引用
6)stl对于错误的处理:
STL错误检查不加,因为降低了效率
(3)容器初始化介绍
1)创建空对象
vector<int>number;
2)初始化10个1
vector<int> number(10,1);
vector<int>::iterator it;
for(it=number.gegin();it!=number.end();++it)
{
cout<<*it<<" ";
}
cout<<endl;
3)传迭代器范围
int arr[10]={1,5,7,9,4,6,8,2,1,20};
vector<int> number(arr,arr+10);
auto it2 = number.begin();
for(;it2!=number.end();++it2)
{
cout<<*it2<<" ";
}
cout<<endl;
4)初始化列表
vector<int> number={1,5,7,9,20};
for(auto &elem:number)
{
cout<<elem<<" ";
}
cout<<endl;
5)赋值
T c;
T d(a);//copy
T e = a; //copy
//***************
T f(std::move(a)); //move
//***************
auto iterB = b.begin();
auto iterE = b.end();
T g(iterB,iterE); //copy
6)额外注意
a) std::forward_list 不提供size(),对空间上的极致效率
b) b.empty(); //return b.size() == 0
c) b.max_size(); 返回container能提供的最大数量
d)if(b ==c){
//比较数量OK
//通过迭代器顺序比较两个容器的值
}
e) 互换方式:
e=b
e=std::move(b)
e.swap(g); //swap很高效,但是除了array ,O(1)
swap(e,g) //O(1),除了std::array
f) e.cbegin ; //const_iterator const的迭代器
auto ea = e.cbegin() ;
auto eea = e.begin();
*eea; //不一定是const引用,得看eea
*ea; / /永远是const的引用
h) e.clear(); //清空容器里面的所有元素,是清空操作,std::array没有这个函数
g) unordered_set 和 unordered_map不支持<号,因为是无序的,靠哈希表的
i) list不提供下标运算符访问
2.容器array
(1)原理(分配在栈上)
(2)以上两者的区别:
std::array<int,100> a; //定义array为a
std::array<int,100> b ={}; //初始化b
(3)接口
(4)访问元素(线程不安全)
(5)迭代器相关
r表示从尾到头
(6)和C的接口互用,例如printf的使用
&carr[0]换成carr.data适应性更好
(7)特殊的地方
carr.fill(0) ; //表示把所有元素都填改为0
(8)异常exception
c.at(pos);在复制、拷贝、交换后会可能越界发生错误
2.array的交换swap真的是值交换,其他container只是指针交换