STL:
String:
运算符重载:+ / = / += / []
注:at和[]的功能类似,就是返回所在位置的引用!
区别在于[]越界会直接报错!at越界会抛出异常!
2.1string类成员函数
构造函数类:
析构函数:前面已经说过string类是管理动态增长字符数组,对于动态申请的空间,需要用到析构函数把它释放掉。不过这里我们无需操作,因为编译器会帮我们默认调用构造函数。
容量成员:
两者区别:
reserve(): serve 是“保留”的词根,所以是用来预留容量的,并不会改变容器的有效元素个数。即用reserve()开辟空间时,仅改变capacity大小,与size无关。
resize(): size 是“大小”的意思,它主要用来调整容器有效元素的个数,有时候也会造成容量的改变。因此用resize()开辟空间时,会对增加的空间全部进行初始化,使得有效元素个数增加。
如果当前字符量小于n, reverse()对剩余容量不做处理,resize()则需要插入一些元素直到空间补满。
两个概念:
容量(capacity): 指容器在自由内存中获得存储空间的大小,容量为100时并不代表有100个元素,可能有效元素只有10个,剩下的90个都是闲置的未定义的内存空间。
大小(size): 指的是容器中实际(有效)元素的个数,当大小为100时,就代表容器中已存在100个元素,容量一定不小于100。
4.1迭代器介绍
string::iterator st1 = s1.begin();
迭代器是一个变量,相当于容器和操纵容器的算法之间的中介。迭代器可以指向容器中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。
迭代器按照定义分为以下四种:
正向迭代器 : --容器类名:iterator 迭代器名;
常量正向迭代器 : -- 容器类名::const_iterator 迭代器名;
反向迭代器 : --容器类名::reverse_iterator 迭代器名;
常量反向迭代器 : --容器类名::const_reverse_iterator 迭代器名;
6.string类对对象的修改操作
find_first_of:
从左往右开始匹配传入字符串或在对象中的任意一个的字符,一旦匹配就返回这个地址!
找不到就返回npos
getline、cin
-
getline: 按行读取, 一次读取多个字符,直到读满N个,或者遇到指定的结束符(自定义的或者EOF或者换行符,不包括空白符)为止。
形式:getline(字符指针,字符个数N,结束符); -
cin读取的话以及 scanf 时,遇到结束符(包括空白符)会终止,只读取空白符之前的部分
vector:
构造初始化:
vector构造函数
(constructor)构造函数 | 说明 |
vector() | 无参数构造 |
vector(size_type n,const value_type& val = value_type()) | 用n个val来构造vector |
vector(const vector& x) | 拷贝构造 |
vector(Inputlterator first,InputIterator last) | 迭代器区间来构造初始化 |
访问元素:
operator[] | 📌 注意事项:operator[] 会用断言检查越界,而 at() 会抛异常。 |
c.at(idx) | 传回索引 idx 所指的数据,如果 idx 越界,抛异常 out_of_range |
vector 空间
容量空间 | 接口说明 |
size | 获取数据个数 |
capacity | 获取容量大小 |
empty | 判断是否为空 |
resize (重点) | 改变 vector 的 size |
reserve (重点) | 改变 vector 放入 capacity |
获取数据个数的 size()
获取 vector 最大存储的 max_size()
string 的 resize 如果不指定 "填充值" ,默认给的是 \0
而 vector 的 resize 如果不指定,默认给的是其对应类型的缺省值作为 "填充值"
这里是 int 就是 0,如果是指针,对应的缺省值就是空指针。
Vector迭代器:
iterator 的使用 | 接口说明 |
begin + end (重点) | 获取第一个数据位置的 iterator/const_iterator, 获取最后一个数据的下一个位置的 iterator/const_iterator |
rbegin + rend | 获取最后一个数据位置的 reverse_iterator, 获取第一个数据前一个位置的 reverse_iterator |
vector 增删查改
vector 增删查改 | 接口说明 |
push_back(重点) | 尾插 |
pop_back (重点) | 尾删 |
find (#include algorithm) | 查找(注意这个是算法模块实现,不是 vector 的成员接口) |
insert | 在 pos 之前插入 val |
erase | 删除 pos 位置的数据 |
swap | 交换两个 vector 的数据空间 |
operator[] (重点) | 像数组一样访问 |
assign() 赋值 | assign 可以把 vector 的内容覆盖掉。允许给一段区间覆盖 |
该 find 和 erase配合使用内部是从 begin 到 end 进行一次遍历,其复杂度是
// 如果有了判断,就不会中断,如果待删目标不存在,就不会去走 erase() 。
// 因为 pos 如果找不到就会等于 end() 上的值,我们利用这一点进行 if 判断,
vector<int>::iterator pos = find(v.begin(), v.end(), 5);
if (pos != v.end()) { v.erase(pos); }
List:
两者的区别:
vector底层实现是数组;list是双向链表。
vector支持随机访问,list不支持。
vector是顺序内存,list不是。
vector在中间节点进行插入删除会导致内存拷贝,list不会。
vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。
6)vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。
两者相关应用:
vector拥有一段连续的内存空间,因此支持随机访问,如果需要高效的随即访问,而不在乎插入和删除的效率,使用vector。
list拥有一段不连续的内存空间,如果需要高效的插入和删除,而不关心随机访问,则应使用list。
list介绍
list是序列容器,允许在序列中的任何位置执行固定O(1)时间复杂度的插入和删除操作,并在两个方向进行迭代。
list容器使用双链表实现;双链表将每个元素存储在不同的位置,每个节点通过next,prev指针链接成顺序表。
list与其他标准序列容器(array,vector和deque)相比,list通常可以在容器内的任何位置插入、提取和移动元素。
list与其他标准序列容器(array,vector和deque)相比,list和forward_list(单链表实现)的主要缺点是他们不能通过位置直接访问元素;例如,要访问列表中的第五个元素,必须从已知位置(开始或结束)迭代到该位置,需要哦线性时间开销。
存储密度低,list要使用一些额外的内容空间(next,prev)来保持与每个元素相关联(前后续的线性)的链接信息,从而导致存储小元素类型(如char,short,int等)的列表的存储密度低。
总的来说:list是双向带头循环列表,内存空间不连续、不支持随机访问。
3.list相关成员函数
成员类型 | 定义 | 笔记 |
value_type | 第一个模板参数 (T) | |
allocator_type | 第二个模板参数(分配) | 默认值为:分配器<value_type> |
参考 | allocator_type::参考 | 对于默认分配器:value_type& |
const_reference | allocator_type:const_reference | 对于默认分配器:常量 value_type& |
指针 | allocator_type::p | 对于默认分配器:value_type* |
const_pointer | allocator_type:const_pointer | 对于默认分配器:常量value_type* |
迭 代 | 指向value_type的双向迭代器 | 可转换为const_iterator |
const_iterator | 用于构造value_type的双向迭代器 | |
reverse_iterator | reverse_iterator<迭代器> | |
const_reverse_iterator | reverse_iterator<const_iterator> | |
difference_type | 有符号整数类型,与以下类型相同:iterator_traits<迭代器>::d验证类型 | 通常与ptrdiff_t相同 |
size_type | 一种无符号整数类型,可以表示difference_type的任何非负值 | 通常与size_t相同 |
3.2 list构造:
构造函数 | 接口说明 |
list() | 构造空的list |
list (size_type n, const value_type& val = value_type()) | 构造的list中包含n个值为val的元素 |
list (const list& x) | 拷贝构造函数 |
list (InputIterator first, InputIterator last) | 用[first, last)区间中的元素构造list |
4.1迭代器简介
迭代器和 vector一样
函数声明 | 接口说明 |
1、begin | 返回第一个元素的迭代器 |
2、end | 返回最后一个元素下一个位置的迭代器 |
3、rbegin | 返回第一个元素的reverse_iterator,即end位置 |
4、rend | 返回最后一个元素下一个位置的reverse_iterator,即begin位置 |
5.元素访问
元素访问 | 功能 |
reference front(); | 返回到容器首元素的引用。 |
const_reference front() const; | 返回到容器首元素的引用 |
reference back(); | 返回到容器中最后一个元素的引用。 |
const_reference back() const; | 返回到容器中最后一个元素 |
list容量:
容量 | 功能 |
bool empty() const; | 检查容器是否无元素,即是否 begin() == end() |
size_type size() const; 返回容器中的元素数, | 即 std::distance(begin(), end()) |
size_type max_size() const; | 返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) |
7.元素修改
修改器 | 功能 |
void clear(); | 从容器擦除所有元素。此调用后 size() 返回零。 |
iterator insert( iterator pos, const T& value ); | 在 pos 前插入 value 。 |
void insert( iterator pos, size_type count, const T& value ); | 在 pos 前插入 value 的 count 个副本。 |
template< class InputIt > | |
void insert( iterator pos, InputIt first, InputIt last); | 在 pos 前插入来自范围 [first, last) 的元素 |
iterator insert( const_iterator pos, std::initializer_list ilist ); | 在 pos 前插入来自 initializer_list ilist 的元素。 |
iterator erase( iterator pos ); | 移除位于 pos 的元素。 |
iterator erase( iterator first, iterator last ); | 移除范围 [first; last) 中的元素。 |
void pop_back(); | 移除容器的末元素。 |
void pop_front(); | 移除容器首元素。 |
void push_front( const T& value ); | 前附给定元素 value 到容器起始。 |
void push_back( const T& value ); | 后附给定元素 value 到容器尾。 |
void resize( size_type count ); | 重设容器大小以容纳 count 个元素。 |
void resize( size_type count, T value = T() ); | count - 容器的大小,value - 用以初始化新元素的值 |
void swap( list& other ); | 将内容与 other 的交换。 |
8.list的操作函数
操作函数 | 功能 |
void merge( list& other ); | 归并二个已排序链表为一个。链表应以升序排序。 |
void reverse(); | 逆转容器中的元素顺序。 |
void unique(); | 从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。 |
void sort(); | 以升序排序元素。保持相等元素的顺序。用 operator< 比较元素 |
list与vector对比
deque容器
Vector容器是单向开口的连续内存空间,deque则是一种双向开口的连续线性空间。所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作
deque构造函数
deque<T> deqT; | 默认构造形式 |
deque(beg, end); | 构造函数将[beg, end)区间中的元素拷贝给本身 |
deque(n, elem); | 构造函数将n个elem拷贝给本身 |
deque(const deque &deq); | 拷贝构造函数 |
deque赋值操作
assign(beg, end); | 将[beg, end)区间中的数据拷贝赋值给本身 |
assign(n, elem); | 将n个elem拷贝赋值给本身 |
deque& operator=(const deque &deq); | 重载等号操作符 |
swap(deq); | 将deq与本身的元素互换 |
deque大小操作
deque.size(); | 返回容器中元素的个数 |
deque.empty(); | 判断容器是否为空 |
deque.resize(num); | 重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除 |
deque.resize(num, elem); | 重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除 |
deque双端插入和删除操作
push_back(elem); | 在容器尾部添加一个数据 |
push_front(elem); | 在容器头部插入一个数据 |
pop_back(); | 删除容器最后一个数据 |
pop_front(); | 删除容器第一个数据 |
deque数据存取
at(idx); | 返回索引idx所指的数据,如果idx越界,抛出out_of_range |
operator[]; | 返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错 |
front(); | 返回第一个数据。 |
back(); | 返回最后一个数据 |
eque插入操作
insert(pos,elem); | 在pos位置插入一个elem元素的拷贝,返回新数据的位置 |
insert(pos,n,elem); | 在pos位置插入n个elem数据,无返回值 |
insert(pos,beg,end); | 在pos位置插入[beg,end)区间的数据,无返回值 |
deque删除操作
clear(); | 移除容器的所有数据 |
erase(beg,end); | 删除[beg,end)区间的数据,返回下一个数据的位置 |
erase(pos); | 删除pos位置的数据,返回下一个数据的位置 |
SET:
set的简介
set是按照一定的次序顺序存储数据的容器。
set的底层是通过二叉搜索树(红黑树)来实现的。
在默认情况下,set底层的二叉树遵循左子节点小于根节点、右子节点大于根节点且不能有相同节点的结构要求。
每个节点的值key具有const属性,不能被修改。
在set中查找某个特定数据的时间复杂度是O(NlogN)。
默认情况下,使用正向迭代器遍历set,是按照中序遍历进行的,也就是说会得到一组升序的数据。
set不可以存储相同的节点,但是multiset可以,multiset与set唯一的不同就是可以存储相同值的节点。
multiset的介绍:
- 1、multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
- 2、在multiset中,元素的value也会识别它(因为multiset中本身存储的就是<value, value>组成的键值对,因此value本身就是key,key就是value,类型为T). multiset元素的值不能在容器中进行修改(因为元素总是const的),但可以从容器中插入或删除。
- 3、在内部,multiset中的元素总是按照其内部比较规则(类型比较)所指示的特定严格弱排序准则进行排序。
- 4、multiset容器通过key访问单个元素的速度通常比unordered_multiset容器慢,但当使用迭代器遍历时会得到一个有序序列。
- 5、multiset底层结构为二叉搜索树(红黑树)。
- 注意:
- 1、multiset中再底层中存储的是<value, value>的键值对
- 2、mtltiset的插入接口中只需要插入即可
- 3、与set的区别是,multiset中的元素可以重复,set是中value是唯一的
- 4、使用迭代器对multiset中的元素进行遍历,可以得到有序的序列
- 5、multiset中的元素不能修改
- 6、在multiset中找某个元素,时间复杂度为O(logN)
- 7、multiset的作用:可以对元素进行排序
正是multiset允许了键值冗余,所以multiset的两个函数接口find和count与set的也是有区别的:
成员函数count | 功能说明 |
set对象 | 值为val的元素存在则返回1,不存在则返回0 |
multiset对象 | 返回set中值为x的元素的个数 |
成员函数find | 功能说明 |
set对象 | 返回值为val的元素的迭代器位置 |
multiset对象 | 返回底层搜索树中序的第一个值为val的元素的迭代器 |
1 构造及赋值相关接口函数
接口函数 | 功能 |
set(const compare& comp = compare) | 默认构造,创建空树 |
set(InputIterator first, InputIterator last, ...) | 使用迭代器区间初始化 |
set(const set& x) | 拷贝构造 |
set& operator=(const set& x) | 赋值运算符重载函数 |
2 通过迭代器遍历set
默认情况下,使用正向迭代器遍历set是进行中序遍历,得到一组升序
2、set的迭代器
函数声明 | 功能介绍 |
begin | 返回set中起始位置元素的迭代器 |
end | 返回set中最后一个元素后面的迭代器 |
cbegin | 返回set中起始位置元素的const迭代器 |
cend | 返回set中最后一个元素后面的const迭代器 |
rbegin | 返回set第一个元素的反向迭代器,即end |
rend | 返回set最后一个元素下一个位置的反向迭代器,即begin |
crbegin | 返回set第一个元素的反向const迭代器,即cend |
crend | 返回set最后一个元素下一个位置的反向const迭代器,即cbegin |
set的容量
函数声明 | 功能介绍 |
bool empty ( ) const | 检测set是否为空,空返回true,否则返回true |
size_type size() const | 返回set中有效元素的个数 |
3 结构修改相关接口函数
接口函数 | 功能 |
pair<iterator,bool> insert(const Type& x) | 在插入值为x的节点 |
void insert(InputIterator first, InputIterator last) | 插入位于一段迭代器区间的数据集 |
size_t erase(const Type& x) | 删除指定值 |
void erase(iterator pos) | 通过给定迭代器位置删除特定节点 |
void clear() | 清空所有节点 |
这里需要注意insert函数的返回值:insert函数返回一键值对,pair中的first数据为iterator类型,如果成功插入节点(set中没有x),则返回新插入节点的位置的迭代器,如果插入节点失败,则返回与x值相同的节点的迭代器。pair中的second数据类型为bool,插入成功返回true,失败返回false。
erase返回被删除的节点的个数,因为set不允许有相同的节点,因此erase返回值只能是1或0,而multiset中erase的返回值则可以大于1,因为multiset中允许相同节点的存在。
当调用erase函数给定值不存在或迭代器位置不合法时:如果使用给定值x的方法删除set的节点且x不存在,那么函数不进行任何工作,直接返回。如果给定不合法的迭代器位置调用erase,那么程序会崩溃。
记录接口:
接口函数 | 功能 |
iterator find(const Type& x) const | 查找特定数据x函数 |
size_t count(const Type& x) const | 统计set中x出现的次数 |
iterator lower_bound (const Type& x) const | 返回小于或等于x的最小节点 |
iterator upper_bound (const Type& x) const | 返回大于x的最小节点 |
pair<iterator,iterator> equal_range (const Type& x) const | 返回包含x的区间 |
find函数如果没有找到值为x的节点,就返回end()的迭代器位置,如果要使用find函数的返回值,保险起见,应当检查 st.find(x) != st.end() 是否成立。
由于set中不允许有相同的节点,count的返回值只能是0或1。
equal返回的区间只包含一个数:[first, second) -- 左开右闭区间,*first = x。
Map/multimap
一. map容器
1. 容器介绍
map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型value_type绑定在一起,为其取别名称为pair: typedef pair value_type;
在内部,map中的元素总是按照键值key进行比较排序的。
map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
注意事项
- map中的的元素是键值对
- map中的key是唯一的,并且不能修改
- 默认按照小于的方式对key进行比较
- map中的元素如果用迭代器去遍历,可以得到一个有序的序列
- map的底层为平衡搜索树(红黑树),查找效率比较高
- 支持[]操作符,operator[]中实际进行插入查找。
multimap容器
multimap和map的唯一不同就是:map中的key是唯一的,而multimap中key是可以重复的。
multimap中没有重载operator[]操作
2. map的参数模板
3. 接口介绍和使用
Construct | 接口说明 |
---|---|
map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()) | 构造空的map |
map (InputIterator first, InputIterator last, const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type()) | 用[first, last)区间的元素构造map |
map (const map& x) | 拷贝构造 |
迭代器
Iterators | 接口说明 |
---|---|
begin | 指向第一个元素的位置 |
end | 指向最后一个元素的下一个位置 |
rbegin | 反向迭代器, 指向最后一个元素 |
rend | 反向迭代器, 指向第一个元素前一个位置 |
cbegin | |
cend | |
crbegin | 下面这四个都是const迭代器, 与上面对应, 加上const所以无法修改内容 |
crend |
map是按照key值有序的容器, 遍历相当于搜索树的中序遍历, 结果按照key有序, 默认是小于比较
特别要注意的是: map容器中的元素是pair类型, 使用迭代器取到的是pair类型, 还要通过pair的first和second来访问数据
元素访问
Element access | 接口说明 |
---|---|
mapped_type& operator[] (const key_type& k) | 通过key找到对应的value, 返回value的引用 |
mapped_type& at (const key_type& k) | 返回key对应的value引用 |
operator[] 支持插入操作, 如果key不存在, 则直接进行插入操作
接口at()也是返回key对应的value引用和[]不同的是, 当key不存在时, 抛异常, 而不会进行插入
容量相关
Capacity | 接口说明 |
---|---|
bool empty ( ) const | 检测map中的元素是否为空, 是返回true,否则返回false |
size_type size() const | 返回map中有效元素的个数 |
修改操作
Modifiers | 接口说明 |
---|---|
pair<iterator,bool> insert (const value_type& x ) | 在map中插入键值对x,注意x是一个键值对,返回值也是键值对:iterator代表新插入元素的位置,bool代表释放插入成功 |
void erase ( iterator position ) | 删除position位置上的元素 |
size_type erase ( constkey_type& x ) | 删除键值为x的元素 |
void erase ( iterator first,iterator last ) | 删除[first, last)区间中的元素 |
void swap (map<Key,T,Compare,Allocator>&mp ) | 交换两个map中的元素 |
void clear ( ) | 将map中的元素清空 |
其他接口:
Operations | 接口说明 |
---|---|
iterator find (const key_type& x) | 在map中查找key为x的元素,找到返回该元素的位置的迭代器,否则返回end |
size_type count (constkey_type& x ) const | 返回key为x的键值在map中的个数,注意map中key是唯一的,因此该函数的返回值要么为0,要么为1,因此也可以用该函数来检测一个key是否在map中 |
equal_range | 返回包含x的区间 |