STL常用容器
- string 容器
- string 的特性
- string 常用 API
- vector 容器
- vector特性
- vector常用API
- deque 容器
- deque 特性
- deque常用API
- stack 容器
- stack 特性
- stack 常用 API
- queue 容器
- queue 特性
- queue常用API
- list 容器
- list 特性
- list 常用 API
- set/multiset 容器
- set/multiset 特性
- set 常用API
- map/multimap容器
- map/multimap 特性
- 对组
- map常用API
string 容器
string 的特性
1)Char是一个指针,String是一个类
string封装了char,管理这个字符串,是一个char*型的容器。
2)String封装了很多实用的成员方法
查找find,拷贝copy,删除delete ,替换replace,插入insert
3)不用考虑内存释放和越界
string管理char*所分配的内存。每一次string 的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。
string和char可以互相转换吗?如果能,怎么转换呢?
可以转换。string转char通过string提供的 c_str() 方法
string 常用 API
string 构造函数
string 基本赋值操作
例子:
s1 = “abcd”;
s2 = ‘a’;
s1.assign(“abcd”);
s1.assign(“abcd”,2);
s2.assign(2,‘a’);
s3.assign(“abcd”,0,2);string 存取字符操作
string中存取字符 [ ] 和 at 的异同?
答: 1 相同, [ ] 和 at都可以返回第n个字符
2 不同,at 访问越界会抛出异常out_of_range,[ ] 越界会直接程序会挂掉。
string 拼接操作
例子:
s1 += s2;
s3 +=a;
s1.append(s2);
s2.append(s3,3);
s3.append(s4,0,2)
s4.append(3,a);string 查找和替换
例子:
s =“abcdefg”;
s.find(“cd”);
s.rfind(“cd”);
s.replace(0,2,“111”);
打印出:111defgstring 比较操作
例子:
s1.compare(s2);string 子串
例子:
string s = “abcdefg”;
string ms = s.sbustr(1,3);
cout<<ms<<endl;
打印出:bcd
string 插入和删除操作
例子:
string s = “abcdefg”;
s.insert(3,“111”);
cout<<s<<endl;
打印出:abc111defg
s.erase(0,2);
打印出:111defg
\
vector 容器
vector特性
vector容器是一个长度动态改变的动态数组,既然也是数组,那么其内存是一段连续的内存,具有数组的随机存取的优点。
vector是动态数组,连续内存空间,具有随机存取效率高的优点。
vector是单口容器,在队尾插入和删除元素效率高,在指定位置插入会导致数据元素移动,效率低。
vector如何实现动态增长?
答: 当vector空间满的时候,再当插入新元素的时候,vector会重新申请一块更大的内存空间,将原空间数据拷贝到新的内存空间,然后释放旧的内存空间,再将新元素插入到新空间中,以此可以看出vector的空间动态增长效率较低。
vector常用API
vector构造函数
vector 常用赋值操作
vector 大小操作
注意:resize 若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
reserve 和resize的区别?
答: reserve 是容器预留空间,但在空间内不真正创建元素对象,所以**在没有添加新的对象之前,不能引用容器内的元素**
resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了.
当我们知道我们存储的元素大概有多少的时候,我们就可以使用reserve方法,来减少vector重新申请内存-拷贝数据-释放旧空间的次数。
vector 数据存取操作
vector 插入和删除操作
deque 容器
deque 特性
deque是“double-endedqueue”的缩写,和vector一样,deque也支持随机存取。
deque 则是一种双向开口的连续性空间,所谓双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,
vector是单向开口的连续性空间,vector当然也可以在头尾两端进行插入和删除操作,但是头部插入和删除操作效率奇差,无法被接受。
deque和vector的最大差异?
一在于deque允许常数时间内对头端进行元素插入和删除操作。
二在于 deque没有容量的概念,因为它是动态的以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来,换句话说,像vector那样“因旧空间不足而重新分配一块更大的空间,然后再复制元素,释放空间”这样的操作不会发生在deque身上,也因此deque没有必要提供所谓的空间保留功能。
缓冲区每一行,不一定是连在一起的,因为deque是动态的以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来,通过中控器维持一种连续内存空间的状态
特性总结:
双端插入和删除元素效率较高.
指定位置插入也会导致数据元素移动,降低效率.
可随机存取,效率高.
deque常用API
deque构造函数
deque赋值操作
deque 大小操作
deque 双端插入和删除操作
deque 数据存取
deque 插入操作
经验之谈:deque是分段连续的内存空间,通过中控器维持一种连续内存空间的状态,其实现复杂性要大于vector queue stack等容器,其迭代器的实现也更加复杂,在需要对deque容器元素进行排序的时候,建议先将 deque容器中数据元素拷贝到 vector容器中,对vector进行排序,然后再将排序完成的数据拷贝回 deque容器。
deque 删除操作
stack 容器
stack 特性
stack 是一种先进后出(first in last out,FILO)的数据结构,它只有一个出口,stack 只允许在栈顶新增元素,移除元素,获得顶端元素,但是除了顶端之外,其他地方不允许存取元素,只有栈顶元素可以被外界使用,也就是说stack 不具有遍历行为,没有迭代器。
特性总结:
栈不能遍历,不支持随机存取,只能通过top从栈顶获取和删除元素.
stack 常用 API
stack 构造函数
stack 赋值操作
stack 数据存取操作
stack 大小操作
思考 : 一个栈的入栈顺序是: a b c d e, 则栈的输出顺序应该为?
输出顺序:e d c b a
\
queue 容器
queue 特性
queue是一种先进先出(firstinfirst out, FIFO)的数据类型,他有两个口,数据元素只能从一个口进,从另一个口出.队列只允许从队尾加入元素,队头删除元素,必须符合先进先出的原则,queue和stack一样 不具有遍历行为。
特性总结:
必须从一个口数据元素入队,另一个口数据元素出队。
不能随机存取,不支持遍历
queue常用API
queue构造函数
queue存取、插入和删除操作
queue赋值操作
queue大小操作
list 容器
list 特性
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。
每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
特性总结:
采用动态存储分配,不会造成内存浪费和溢出
链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
链表灵活,但是保存结点与结点之间的前驱后继,需要空间和时间额外耗费较大
list 常用 API
list 构造函数
list 数据元素插入和删除操作
list 大小操作
list 赋值操作
list 数据的存取
list 反转排列排序
算法sort 支持可随机访问的容器,
而list容器是不可随机访问的,但是 list容器里面有自己的sort排序
sort排序 默认是 从小到大
而想要从大到小 降序,则需要一个回调函数来判断排序
bool mycompare(int v1, int v2){
return v1 > v2 ;
}
mlist.sort(mycompare);
链表和数组有什么区别?
- 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
- 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据元素。(数组中插入、删除数据项时,需要移动其它数据项)
\
set/multiset 容器
set/multiset 特性
set/multiset的特性是所有元素会根据元素的值自动进行排序。set 是以RB-tree(红黑树,平衡二叉树的一种)为底层机制,其查找效率非常好。set 容器中不允许重复元素,multiset允许重复元素。
我们可以通过set的迭代器改变元素的值吗?
答: 不行,因为set集合是根据元素值进行排序,关系到set的排序规则,如果任意改变set的元素值,会严重破坏set组织。
set 常用API
set构造函数
set赋值操作
set大小操作
set插入和删除操作
set查找操作
我们发现打印出来set集合中的元素是从小到大的升序排列,那么我们如何指定排序为降序呢?这个问题呢?我们需要了解函数对象的概念。
set排序 默认是 从小到大
可以利用仿函数,从大到小排序
class mycompare{
public:
bool operator()(int v1 ,int v2){
return v1 > v2;
}
};
set<int , mycompare> s1;
、
map/multimap容器
map/multimap 特性
map相对于set区别,map具有键值和实值,所有元素根据键值自动排序。pair的第一元素被称为键值,第二元素被称为实值。map也是以红黑树为底层实现机制。
我们通过map的迭代器可以修改map的键值吗?
答案是否定的,键值关系到容器内元素的排列规则,任意改变键值会破坏容器的排列规则,但是你可以改变实值。
map和multimap区别在于,map不允许相同key值存在,multimap则允许相同key值存在。
、
对组
对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有函数 first 和 second 访问。
类模板:template <class T1, class T2> struct pair.
map常用API
map构造函数
map赋值操作
map大小操作
map插入数据元素操作
注意:
前三种方法,采用的是insert()方法,该方法返回值为pair<iterator,bool>
第四种方法非常直观,但存在一个性能的问题。插入5时,先在mapStu中查找主键为5的项,
若没发现,则将一个键为5,值为初始化值的对组插入到mapStu中,然后再将值修改成“小王”。
若发现已存在5这个键,则修改这个键对应的value。
string strName = mapStu[2];
//取操作或插入操作只有当mapStu存在2这个键时才是正确的取操作,否则(即mapStu不存在键值为2的)会自动插入一个实例, 键值为2,实值为初始化值0。
map 删除操作
map 查找操作