C++string类库:<string> 见Primer77
-字符操作<cctype>
-容器的统一接口
-string类特有接口
C++数组和兼容C代码字符串的接口:
-C++11标准库为了契合容器/迭代器的概念,提供begin()end(),来返回数组的首尾指针
-C风格字符串:<string.h> (字符数组,以及标准接口)
-strlen(), strcmp(), strcat(), strcpy()
-char *str = s.c_str();C++string类,提供了返回一个字符串数组指针的接口
-vector<int> ivec(begin(arry), end(arry));用数组的一部分初始化vector
C++类模板:容器
C++容器:(某一种类型对象的集合,可以是内置数据类型,内置类,或者自定义数据类型)
-顺序容器(元素按插入顺序排序)
-以数组为基本结构:vector、string、array、deque
-以链表为基本结构:list、forward_list
-概念区分:内置数组,array,vector
Array可以进行拷贝赋值(接近容器的特征),定长(接近内置数组)
Vector不定长且可以拷贝赋值但是连续存储这一点不变(顺序容器本质)
(此外由于vector是不定长的,所以可以进行列表拷贝赋值 ‘= { }’)
-关联容器
-容器初始化 **<**> **{**,**,**,----} // **<**> ** = {**,**,**,------}
-容器接口(vextor为例):详见Primer295(容器类有很多成员是共性的!还有成员类)
-v.push_back(a)
-v.empty();
-v.size()
-v[n]
-v1 = v2
-v = {***,***----}拷贝赋值
-v1 == v2 || v1 != v2
-<, <=, >, >= 字典顺序进行比较
-v.begin() || v.end() 返回容器元素对象的指针
-迭代器(指向容器对象的指针,可用于遍历不可进行下标访问的容器)
-auto it = v.begin() || v.end()
-迭代器遍历容器 if(s.begin != s.end()){******} 容器使用隐式迭代器进行循环
-* it
-*(++it) || *(--it)
- == || !=
-迭代器类型:**::iterator it || **::const_iterator it (读写迭代器和只读迭代器)
-翻转迭代器reverse_iterator
-容器共有接口以及成员类:
-接口:
-构造函数初始化(声明时和assign时可用)或者拷贝初始化(拷贝对象或者列表)
-首指针与尾后指针a.bgin( ); a.end( );
-交换swap( ): swap(a, b)
实际上swap换的是名字,即原本属于a的所有成员在swap之后全部属于b,例如迭代器指向a的数据,swap之后迭代器 指向b的数据,很重要的一点是:swap换名字那么就是没有对数据拷贝,所以时间复杂度为常数。但是swap对array采用的是拷贝内容
-关系运算符(比较元素个数与第一个不同元素的大小关系)
-大小a.size(); a.max_size(); a.empty();
Forward_list不支持a.size( )
-成员类
-**<>::iterator/const_iterator/reverse_iterator/const_reverse_iterator
-**<>::value_type() 数据成员构造函数
-顺序容器的特有接口
-共有:
-定义容器a.assign( ) :a.assign(it0,it1);a.assign(n,t); a.assign(b)
实际上复现了声明时的构造函数,此操作不适用于array
-添加元素1>a.push_back( ); a.push_front( );a.emplace_back( );emplace_front( )
2>a.insert(p,t)/insert(p,n,t)/insert(p,b,e)/insert(p,il);a.emplace(p,args)
【注】1>类型插入头或尾2>类型插入指定位置之前;并且insert是拷贝传入的对象或者列表,接口返回插入位置迭代器;emplace的参数是一个数据成员的参数,emplace会调用成员的构造函数生成一个成员对象(直观的就是emplace的参数就是拷贝插入类型的列表元素)
【注】forward_list不支持任意位置插入,他有自己的插入操作;并且不支持再尾部插入(即forward);vector和string不支持头部插入操作;他们的增长方向是有规定的。
-访问元素: p = it迭代器访问(所有都支持),下标访问a.at()/a[ ](快速随
机访问必须是以数组为基本结构的容器才能使用:vector,string,array,deque)a.front()/back()返回首尾元
素的迭代器类型指针,而且容器必须非空b.begin()/end()返回首元素和尾后元素迭代器类型指针。
罗列访问接口:a.back( )/front( ); a.at( ); a[ ]
【注】发现访问接口返回的都是迭代器,标签访问返回的是元素对象
-删除元素:a.pop_back( )/pop_front( ); a.erase( p)/erase(b, e); a.clear( )
删除首尾元素,删除任意位置元素(不能用尾后位置传参)
【注】容器接口常为元素对象和迭代器类型的参数
-改变容器大小:a.resize(size, value)
Size为新的容量,value可以省略,表示新增容量的初始化值
【注】容量改变引起的迭代器失效C++Prinmer 315
概括的来说可以随机访问的顺序容器(vector,string,deque)
如果重新定义容量必然引起迭代器失效,如果是插入删除操作,
内存空间未被移动的元素位置上的迭代器仍然有效;
-特有:
-forward_list的特殊操作 详见C++ Primer:305加入元素 313删除元素
-vector的特性:a.capacity()返回一次性分配给vector的空间大小。
a.shrink_to_fit( )将capacity调整至和size一样大
c.reserve( n)给vector申请一个可以容纳n个元素的空间
-string的特性1>包含以上特性
2>string其他构造方法:s(cp,n)将cp指向的数组的前n个元素
拷贝到s中;s(s2,pos)/(s2,pos,n)将s2从pos开始的元素拷贝至s
3>子串操作:s.(pos,n)/(pos)返回一个从pos开始的(n长)子串。
【注】此处的pos是下标,而不是迭代器,string是支持随机访问的
4>改变string内容的其他方法:详见C++Primer 323
s.insert(pos,args); s.erase(pos,len); s.append(args);
s.replace(range,args)【注】range可以是下标亦可以是迭代器对。
5>字符串搜索操作:s.find(args)/rfind(args)第一次和最后一次出现
s.find_first_of(args)/find_last_of(args)实例中任何一个字符。。
s.find_first_not_of(args)/***_last_***(args)
6>元素的同符号数值转换:
1、To_string( val)数到字符串
2、Stoi(s);stol(s);stoul(s);stoll(s);stoull(s);stof(s);stod(s);stold(s)
-队列和栈-顺序容器适配器: stack\queue(单端队列)\priority_queue(优先队列)
-适配器共有操作:a.empty();a.size();a.swap(b)/swap(a,b)
-stack:a.pop( );a.push(t);a.emplace(args);a.pop( );
-queue:a.pop( );a.push( );a.front( );a.back( );a.emplace( )
-priority_queue: a.top( )/pop( );a.pop( );a.emplace( )
【注】1>优先队列,可以自定义优先级;定义方法类似c语言字符串比
较函数传入的判决函数指针。
2>deque是一个双端队列,也可以理解为deque将vector或queue变成了双端操作。
-关联容器:关联容器改善了链表为基础的数据结构的查找功能,比如顺序容器中list和
Forward_list不可以下标访问的弊端,map和unordered_map则可以支持高效
的关键字查找(从自动排序这一点,来看就是使用了树或者图的数据结构)
Map和set一共有八种关联容器,用是否允许重复(unordered)和是否
允许重复关键字(multi)进行组合。
-定义关联容器:
-有序容器的默认字典顺序排序以及关键字类型的比较函数,例如
Multiset<t,decltype(pfunction)*>, pfunction是一个布尔型函数。
-pair类型:p.first, p.second, make_pair(t1,t2)
-关联容器的操作:通常不对关联容器使用泛型算法
-内部类型别名:key_type, mapped_type, value_type
【注】map中value_type即pair<const key_type, mapped_type>,亦表明
在map中value_type肯定是个类 类型的别名
-访问元素:
1>a.find(t); a.count(t);
2>a.lower_bound(t)/upper_bound(t)返回第一个不小于/不大于关键字的元素指针
a.equal_range( t)返回一个迭代器pair指向等于标签t的元素范围,若没有,则均指向容器尾后。c.end( ).
-插入操作:a.insert(b,e)/insert(p,t)/(il); a.emplace(args)/emplace(p,args)
【注】区别于顺序容器的任意位置插入方法,关联容器插入的p参数,是被返
返回的迭代器位置,而不是一个指定位置。
-删除元素:a.erase(t)删除关键字为t的元素,返回删除的数量
a.erase(p)删除迭代器指向的的元素,返回指向其后元素的迭代器
a.erase(b,e)删除范围元素,返回尾后元素位置
-无序关联容器的额外接口:unordered容器采用哈希映射和桶来维护数据
-桶接口:a.bucket_count( ); a.max_bucket_count( ); 目前桶数量和最多桶数量
a.bucket_size(n)第n个桶的容量,a.bucket(t)元素t在哪个桶
-桶迭代:1>**<pair>::local_iterator/const_local_iterator该容器桶迭代器类型
2>a.begin(n)/end(n)/cbegin(n)/cend(n)返回桶n的迭代器
-哈希策略:详见C++Primer395
-泛型算法:1、通用的独立于容器的算法.多数算法都定义在头文件algorithm中,此外还在
Numeric中定义了一组数值泛型算法:一般情况下,数字泛型算法的接口要求传入一
个遍历范围,然后对范围元素进行操作。
2、泛型算法不依赖于容器类型的原因:访问容器的操作由迭代器完成,迭代器使得
泛型算法不依赖于容器,但是对元素的操作是需要指定元素类型的。
3、需要理解泛型算法的操作是在容器的上层完成的,实现对容器操作的统一接口。
-只读算法:
find(),equal()
-写元素算法
Fill(),fill_n(),back_insert(),copy()
-重排元素算法
消除重复元素unique,先排序然后删除重复位置的元素
-定制操作:
-向算法传函数(算法的回调函数)
1>“谓词”判决条件回调函数指针2>迭代器范围传参,并传给了谓词