Fork me on GitHub

STL の 概念及其应用

1.队列queue

   queue是STL中实现“先进先出”的一个容器。 使用queue。必须加#include<queue>using namespace std;   queue<typename> name; 

  常用函数: 

  (1) push()  :将x入队,时间复杂度为O(1)。  

  (2) front()back()    :它们分别用来获得队首元素和队尾元素,时间复杂度为O(1),

queue<int> q;
for(int i = 1; i <= 5; i ++) 
    q.push(i);
  printf(“%d  %d\n”, q.front(), q.back());

  (3) pop() :用来让队首元素出队,时间复杂度为O(1)。  

  (4) empty()  :用来检测queue是否为空,返回true或者false,时间复杂度为O(1)。需要注意,在使用front()和pop()前,必须用empty()来判断队列是否为空。 

  (5) size() :返回queue内元素的个数,时间复杂度为O(1)。  

2、栈stack

  stack是STL中实现“后进先出”的一个容器。 使用stack,必须加#include<stack>using namespace std;   stack<typename> name; 

  常用函数: 

  (1) push() :push(x)将x压栈,时间复杂度为O(1)。 

   (2) top() :用来获得栈顶元素,时间复杂度为O(1),例如以下代码输出5:   

stack<int> st;
for(int i = 1; i <= 5; i ++) 
    st.push(i);
printf(“%d\n”,  st.top());

   (3) pop()  :用来弹出栈顶元素,时间复杂度为O(1),注意pop()是删不是取。  

   (4) empty() :用来检测stack是否为空,空返回true,非空返回false,时间复杂度 为O(1)。  

   (5) size() :size()返回stack内元素的个数,时间复杂度为O(1)。  

3.变长数组vector

   vector直译为“向量”,一般说成“变长数组”,也就是长度根据需要而自动改变的数组,有些题目需要开很多数组,往往造成内存超限,使用vector简单方便,还可节省空间,使用vector,必须加#include<vector>using namespace std;

  vector<typename> name;

以上定义相当于定义了一个一维数组name[size],只是size不确定,其长度可以根据需要而变化。其中,typename可以是任何基本类型,如int、double、char、结构体等,也可以是容器。 

vector<int> a;                 //定义了一个整型不定长数组a     
vector<double> score;   //定义了一个双精度浮点型不定长数组score
vector<node> stu;          //定义了一个结构体类型的不定长数组stu

注意:如果typename也是一个STL容器,那么定义时需要在两个“>”符号之间加一个空格,不然编译器会误认为是位运算的右移符号“>>”,例如: 

vector<vector<int>  > a;  //定义了一个两个维度都可变的二维整型数组a 
    
vector<int> a[100];           //定义了一个第一维长度为100,第二位不限长度的二维数组a

 

vector的访问:

  访问vector中的元素一般有两种方式:下标访问 和 迭代器(iterator)访问。 

  第一种是通过“下标”访问的。例如,对于容器vector<int> v,可以使用v[index]来访问它的第index个元素。其中,0≤index≤v.size() – 1。 

  第二种是通过“迭代器”访问的。可以将迭代器理解为一种类似指针的变量,使用前需要提前定义,其定义为:vector<typename>::iterator it,这个it就是一个迭代器,可以通过“*it”来访问该容器里的元素值,下面举个例子: 

vector<int>::iterator it = v.begin();   //定义一个迭代器it,初始化为容器v的首元素地址,这是*it相当于v[0],*(it + i)相当于v[i]。

  迭代器还可以进行自加自减操作,如it++++itit----it,注意:迭代器不支持“it<v.end()”的写法,只能是“it != v.end()”, v.end()并不是取v容器尾元素地址,而是尾元素下一个地址。  例:

for(vector<int>::iterator it = v.begin(); it != v.end(); it ++) 
    printf(“%d”,*it); 

 

常用函数: 

(1) push_back() :push_back(x)将x添加到容器最后,时间复杂度为O(1)。 

 (2) size()   :如果是一维数组,size()用来获得vector中元素个数;如果是二维数组,size()用来获得vector中第二维的元素个数,时间复杂度为O(1),同时,还可以使用resize(n)重设数组大小。例如以下代码输出12300: 

vector<int> v;
  for(int i = 1; i <= 3; i ++) v.push_back(i);
  v.resize(5);
  for(int i = 0; i < v.size(); i ++) printf(“%d”,v[i]);

 (3) pop_back() :用来删除vector中的尾元素。时间复杂度为O(1),例如以下代码输出12: 

 (4) clear() :用来清空vector中的所有元素。时间复杂度为O(n),例如以下代码输出0:

 (5) insert() :insert(it, x)用来向vector任意迭代器it前插入元素x。时间复杂度为O(n),例如以下代码输出1 2 -1 3 4 5: 

vector<int> v;
for(int i=1;i<=5;i++) v.push_back(i);
vector<int>::iterator it=v.begin();
v.insert(it+2,-1);
for(;it!=v.end();it++) printf("%d ",*it);

 (6) erase() :erase()用来删除vector中的元素,有两种用法,一是erase(it),删除迭代器it处的单个元素;二是erase(first, last),删除左闭右开区间[first, last)内的所有元素。例如: 

 

4、优先队列priority_queue 

   priority_queue翻译为优先队列,一般用来解决一些贪心问题,其底层是用堆来实现的。在优先队列中,任何时刻,队首元素一定是当前队列中优先级最高的那一个。使用优先队列,也必须加#include<queue>using namespace std;。 

   priority_queue<typename> name; 

  注意:和queue不一样的是,priority_queue没有front()和back(),而只能通过top()或pop()访问队首元素(也成为堆顶元素),也就是优先级最高的元素。 

  常用函数: 

  (1)push():push(x)是将x加入优先队列,时间复杂度为O(log2n),n为当前优先队列中的元素个数。加入后会自动调整priority_queue的内部结构,以保证队首元素(堆顶元素)的优先级最高

  (2)top() :top()是获取队首元素(堆顶元素),时间复杂度为O(1)。

  (3)pop()    :pop()是让队首元素(堆顶元素)出队,由于出队后要调整堆内部结构,所以时间复杂度是O(log2n)

 

  优先队列优先级如何设置: 

//大根堆优先队列的定义:    
priorty_queue<int> q;            //默认为大顶堆优先队列
priorty_queue<int,vector<int>,less<int>  > q;
//小根堆优先队列的定义:    
priorty_queue<int,vector<int>,greater<int>  > q;

 

5、映射map 

   map翻译为映射,其实数组就是一种映射。比如int a[100];,就是定义了一个int到int的映射,而a[5]=25;是把下标5映射到值25,他们是一一对应的,数组总是把int类型映射到其它基本类型,因为数组下标只能是int。但有时希望把string映射成一个int,数组就不方便了这时就可以使用map,它可以将任何基本类型(包括容器)映射到任何基本类型。 使用map,也必须加#include<map>using namespace std;

  map常用的三种情形:

    1.需要建立字符(串)与整数之间的映射,使用map可以减少代码量;

    2.判断大整数(比如几千位)或者其它类型数据是否存在,可以把map当bool类型数组使用(哈希表);

    3. 字符串与字符串之间的映射。  

  定义:

  map<typename1, typename2> name; 

  其中,typename1是映射前的类型(键key),typename2是映射后的类型(值value),name为映射的名字,例: 

  普通int数组就是:map<int, int> mp;

  字符串到整型的映射:map<string, int> mp;

  键和值也可以是容器:map<set<int>, string> mp;

   当然,map的键对值必须唯一(也就是键key必须唯一,值value不一定) 

 

 map的访问:

  map的访问依然是下标访问和迭代器访问两种。 

  下标访问(例): map<char, int> mp; mp[‘c’] 来访问它对应的元素,如mp[‘c’] = 124。 

  迭代器访问(例): map<typename1, typename2>::iterator it; 因为map的每一对映射都有两个typename,所以使用“it -> first”来访问键,而使用“it -> second”来访问值。例如: 

map<char, int> mp;
mp[‘m’] = 20;     mp[‘r’] = 30;     mp[‘a’] = 40;
for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it ++)
	printf(“%c %d\n”,it -> first, it -> second);

  map在建立映射的同时,会自动实现按照键从小到大排序。因为map内部使用“红黑树”实现,后面set也是。

 

  map的常用函数: 

   (1)find() 和 size() :find(key)是返回键为key的映射的迭代器,时间复杂度为O(log2n),n为map中映射的对数。size()用来获得map中映射的对数,时间复杂度为O(1)。

  (2)erase() :erase()可以删除单个元素,也可以删除一个区间内的所有元素。删除单个元素可以用erase(it),其中it为要删除元素的迭代器,时间复杂度为O(1)。也可以用erase(key),key为要删除元素的键,时间复杂度为O(log2n)。删除一个区间内所有元素用erase(first, last)。其中,first为区间的起始迭代器;last为区间的末尾迭代器的下一个地址,也就是左闭右开区间[first, last) 。时间复杂度为O(first - last)。

   (3)clear() :用来清空map。时间复杂度为O(n)。 

 

6.二元结构体pair 

  pair是”二元结构体”的替代品,将两个元素捆绑在一起,节省编码时间。相当于一下定义:

struct pair {
       typename1 first;
       typename2 second;
};

  要使用pair,必须先添加头文件,即#include<utility>,同时需要using namespace std;。因为map的内部实现涉及pair,因此添加map头文件时会自动添加utility头文件,此时可以省去utility头文件。

  pair<typename1, typename2> name; 

  初始化:例如:定义一个参数为string和int类型的pair,并同时初始化: 

   写法一:make_pair(“haha”, 5);  

   写法二:pair<string, int> p(“haha”, 5);      

写法三
 pair<string, int> p;       
p.first = “haha”;
p.second = 5;

    pair可以直接做比较运算,比较的规则是先以first的大小作为标准,只有当first相等时才去判断second的大小。 

  由于map可以根据键值自动排序,而pair又可以比较大小,所以pair可插入到同类型的map中并根据it->first排序,(注意,如果it->first相同则根据map键值唯一的特性,只保留先输入的二元组) 

 

7.集合set

   set翻译为集合,是一个内部自动有序且不含重复元素的容器。set最主要的作用就是自动去重并按升序排序,因此遇到需要去重但是又不方便直接开数组的情况,比如元素比较多或者类型不是int,可以尝试用set解决。set中的元素是唯一的,其内部采用“红黑树”实现。 使用set,也必须加#include<set>using namespace std;。 

  set<typename> name; 

  其中,typename可以是任何基本类型或者容器,name是集合的名字,例: set<int> st; 

   也可以定义set数组,例:set<int> st[100]; 

  这样st[0] ~ st[99]中的每一个元素都是一个set容器。 

  set的访问:

  set只能通过迭代器访问,即先定义一个迭代器: set<typename>::iterator it; 

  然后使用“*it”来访问set中的元素。Set也不支持“*(it+i)”和“it<st.end()”的访问方式,实际上除了vector和string之外的STL容器都不支持。

  set的常用函数: 

  (1)insert() 和 size() :insert(x)用来将x插入到set中,并自动递增排序和去重,时间复杂度为O(log2n),n为set中元素的个数。size()用来获得set中的元素个数,时间复杂度为O(1)。 

   (2)find() :find(value)是返回set中对应值value的迭代器(可以把it看成地址,*it看成地址对应的值),时间复杂度为O(log2n)。例如以下一段代码输出“3 2”。 

set<int> st;
for(int i = 1; i <= 3; i ++) st.insert(i);
printf(“%d”, st.size());
printf(“%d”, *(st.find(2)));

  (3)clear():clear()用来清空set中的所有元素,时间复杂度为O(n)。 

  (4)erase() :erase()可以删除单个元素,也可以删除一个区间内的所有元素。删除单个元素可以用erase(it),其中it为要删除元素的迭代器,时间复杂度为O(1)。也可以用erase(value),value为要删除元素的值,时间复杂度为O(log2n)。删除一个区间内所有元素用erase(first, last)。其中,first为区间的起始迭代器;last为区间的末尾迭代器的下一个地址,也就是左闭右开区间[first, last) 。时间复杂度为O(first - last)。

8.bitset

LINK

  std::bitset 是标准库中的一个存储 0/1 的大小不可变容器。严格来讲,它并不属于 STL。

  由于内存地址是按字节即 byte 寻址,而非比特bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存。

  bitset 就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的 0/1

  对于一个 4 字节的 int 变量,在只存 0/1 的意义下,bitset 占用空间只是其 ,计算一些信息时,所需时间也是其 。

在某些情况下通过 bitset 可以优化程序的运行效率。至于其优化的是复杂度还是常数,要看计算复杂度的角度。一般 bitset 的复杂度有以下几种记法:(设原复杂度为 )

  1. ,这种记法认为 bitset 完全没有优化复杂度。
  2. ,这种记法不太严谨(复杂度中不应出现常数),但体现了 bitset 能将所需时间优化至 。
  3. ,其中 (计算机的位数),这种记法较为普遍接受。
  4. ,其中  为计算机一个整型变量的大小。

当然,vector 的一个特化 vector<bool> 的储存方式同 bitset 一样,区别在于其支持动态开空间,bitset 则和我们一般的静态数组一样,是在编译时就开好了的。

然而,bitset 有一些好用的库函数,不仅方便,而且有时可以避免使用 for 循环而没有实质的速度优化。因此,一般不使用 vector<bool>

 

使用

头文件

1
#include <bitset>

指定大小

1
bitset<1000> bs;  // a bitset with 1000 bits

构造函数

  • bitset(): 每一位都是 false
  • bitset(unsigned long val): 设为 val 的二进制形式。
  • bitset(const string& str): 设为  串 str

运算符

  • operator []: 访问其特定的一位。
  • operator ==/!=: 比较两个 bitset 内容是否完全一样。
  • operator &/&=/|/| =/^/^=/~: 进行按位与/或/异或/取反操作。bitset 只能与 bitset 进行位运算,若要和整型进行位运算,要先将整型转换为 bitset
  • operator <>/<<=/>>=: 进行二进制左移/右移。
  • operator <>: 流运算符,这意味着你可以通过 cin/cout 进行输入输出

成员函数

  • count(): 返回 true 的数量。
  • size(): 返回 bitset 的大小。
  • test(pos): 它和 vector 中的 at() 的作用是一样的,和 [] 运算符的区别就是越界检查。
  • any(): 若存在某一位是 true 则返回 true,否则返回 false
  • none(): 若所有位都是 false 则返回 true,否则返回 false
  • all():C++11,若所有位都是 true 则返回 true,否则返回 false
    1. set(): 将整个 bitset 设置成 true
    2. set(pos, val = true): 将某一位设置成 true/false
    1. reset(): 将整个 bitset 设置成 false
    2. reset(pos): 将某一位设置成 false。相当于 set(pos, false)
    1. flip(): 翻转每一位。(,相当于异或一个全是  的 bitset
    2. flip(pos): 翻转某一位。
  • to_string(): 返回转换成的字符串表达。
  • to_ulong(): 返回转换成的 unsigned long 表达 (long 在 NT 及 32 位 POSIX 系统下与 int 一样,在 64 位 POSIX 下与 long long 一样)。
  • to_ullong():C++11,返回转换成的 unsigned long long 表达。

一些文档中没有的成员函数:

  • _Find_first(): 返回 bitset 第一个 true 的下标,若没有 true 则返回 bitset 的大小。
  • _Find_next(pos): 返回 pos 后面(下标严格大于 pos 的位置)第一个 true 的下标,若 pos 后面没有 true 则返回 bitset 的大小。

List 容器

list是C++标准模版库(STL,Standard Template Library)中的部分内容。实际上,list容器就是一个双向链表,可以高效地进行插入删除元素。

使用list容器之前必须加上<vector>头文件:#include<list>;

list属于std命名域的内容,因此需要通过命名限定:using std::list;也可以直接使用全局的命名空间方式:using namespace std;

构造函数

    list<int> c0; //空链表

  list<int> c1(3); //建一个含三个默认值是0的元素的链表

  list<int> c2(5,2); //建一个含五个元素的链表,值都是2

  list<int> c4(c2); //建一个c2的copy链表

  list<int> c5(c1.begin(),c1.end()); ////c5含c1一个区域的元素[_First, _Last)。

成员函数

c.begin()      返回指向链表第一个元素的迭代器。

c.end()      返回指向链表最后一个元素之后的迭代器。

1     list<int> a1{1,2,3,4,5};
2     list<int>::iterator it;
3     for(it = a1.begin();it!=a1.end();it++){
4         cout << *it << "\t";
5     }
6     cout << endl;

c.rbegin()      返回逆向链表的第一个元素,即c链表的最后一个数据。

c.rend()      返回逆向链表的最后一个元素的下一个位置,即c链表的第一个数据再往前的位置。

1     list<int> a1{1,2,3,4,5};
2     list<int>::reverse_iterator it;
3     for(it = a1.rbegin();it!=a1.rend();it++){
4         cout << *it << "\t";
5     }
6     cout << endl;

operator=      重载赋值运算符。

1     list<int> a1 {1,2,3,4,5},a2;
2     a2 = a1;
3     list<int>::iterator it;
4     for(it = a2.begin();it!=a2.end();it++){
5         cout << *it << endl;
6     }

c.assign(n,num)      将n个num拷贝赋值给链表c。

c.assign(beg,end)      将[beg,end)区间的元素拷贝赋值给链表c。

复制代码
 1     int a[5] = {1,2,3,4,5};
 2     list<int> a1;
 3     list<int>::iterator it;
 4     a1.assign(2,10);
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     a1.assign(a,a+5);
10     for(it = a1.begin();it!=a1.end();it++){
11         cout << *it << " ";
12     }
13     cout << endl;
复制代码

c.front()      返回链表c的第一个元素。

c.back()      返回链表c的最后一个元素。

1     list<int> a1{1,2,3,4,5};
2     if(!a1.empty()){
3         cout << "the first number is:" << a1.front() << endl;
4         cout << "the last number is:" << a1.back() << endl;
5     }

c.empty()  判断链表是否为空。

1     list<int> a1{1,2,3,4,5};
2     if(!a1.empty())
3         cout << "a1 is not empty" << endl;
4     else
5         cout << " a1 is empty" << endl;

c.size()      返回链表c中实际元素的个数。

1     list<int> a1{1,2,3,4,5};
2     cout << a1.size() << endl;

c.max_size()      返回链表c可能容纳的最大元素数量。

1     list<int> a1{1,2,3,4,5};
2     cout << a1.max_size() << endl;

c.clear()      清除链表c中的所有元素。

复制代码
 1     list<int> a1{1,2,3,4,5};
 2     list<int>::iterator it;
 3     cout << "clear before:";
 4     for(it = a1.begin();it!=a1.end();it++){
 5         cout << *it << "\t";
 6     }
 7     cout << endl;
 8     a1.clear();
 9     cout << "clear after:";
10     for(it = a1.begin();it!=a1.end();it++){
11         cout << *it << "\t";
12     }
13     cout << endl;
复制代码

c.insert(pos,num)      在pos位置插入元素num。

c.insert(pos,n,num)      在pos位置插入n个元素num。

c.insert(pos,beg,end)      在pos位置插入区间为[beg,end)的元素。

复制代码
 1     list<int> a1{1,2,3,4,5};
 2     list<int>::iterator it;
 3     cout << "insert before:";
 4     for(it = a1.begin();it!=a1.end();it++){
 5         cout << *it << " ";
 6     }
 7     cout << endl;
 8     
 9     a1.insert(a1.begin(),0);
10     cout << "insert(pos,num) after:";
11     for(it = a1.begin();it!=a1.end();it++){
12         cout << *it << " ";
13     }
14     cout << endl;
15     
16     a1.insert(a1.begin(),2,88);
17     cout << "insert(pos,n,num) after:";
18     for(it = a1.begin();it!=a1.end();it++){
19         cout << *it << " ";
20     }
21     cout << endl;
22 
23     int arr[5] = {11,22,33,44,55};
24     a1.insert(a1.begin(),arr,arr+3);
25     cout << "insert(pos,beg,end) after:";
26     for(it = a1.begin();it!=a1.end();it++){
27         cout << *it << " ";
28     }
29     cout << endl;
复制代码

c.erase(pos)    删除pos位置的元素。

复制代码
 1     list<int> a1{1,2,3,4,5};
 2     list<int>::iterator it;
 3     cout << "erase before:";
 4     for(it = a1.begin();it!=a1.end();it++){
 5         cout << *it << " ";
 6     }
 7     cout << endl;
 8     a1.erase(a1.begin());
 9     cout << "erase after:";
10     for(it = a1.begin();it!=a1.end();it++){
11         cout << *it << " ";
12     }
13     cout << endl;
复制代码

c.push_back(num)      在末尾增加一个元素。

c.pop_back()      删除末尾的元素。

c.push_front(num)      在开始位置增加一个元素。

c.pop_front()      删除第一个元素。

复制代码
 1     list<int> a1{1,2,3,4,5};
 2     a1.push_back(10);
 3     list<int>::iterator it;
 4     cout << "push_back:";
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     a1.pop_back();
11     cout << "pop_back:";
12     for(it = a1.begin();it!=a1.end();it++){
13         cout << *it << " ";
14     }
15     cout << endl;
16     
17     a1.push_front(20);
18     cout << "push_front:";
19     for(it = a1.begin();it!=a1.end();it++){
20         cout << *it << " ";
21     }
22     cout << endl;
23     
24     a1.pop_front();
25     cout << "pop_front:";
26     for(it = a1.begin();it!=a1.end();it++){
27         cout << *it << " ";
28     }
29     cout << endl;
复制代码

resize(n)      从新定义链表的长度,超出原始长度部分用0代替,小于原始部分删除。

resize(n,num)            从新定义链表的长度,超出原始长度部分用num代替。

复制代码
 1     list<int> a1{1,2,3,4,5};
 2     a1.resize(8);
 3     list<int>::iterator it;
 4     cout << "resize(n):";
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     a1.resize(10, 10);
11     cout << "resize(n,num):";
12     for(it = a1.begin();it!=a1.end();it++){
13         cout << *it << " ";
14     }
15     cout << endl;
复制代码

c1.swap(c2);      将c1和c2交换。

swap(c1,c2);      同上。

复制代码
 1     list<int> a1{1,2,3,4,5},a2,a3;
 2     a2.swap(a1);
 3     list<int>::iterator it;
 4     cout << "a2.swap(a1):";
 5     for(it = a2.begin();it!=a2.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     swap(a3,a2);
11     cout << "swap(a3,a2):";
12     for(it = a3.begin();it!=a3.end();it++){
13         cout << *it << " ";
14     }
15     return 0;
复制代码

c1.merge(c2)      合并2个有序的链表并使之有序,从新放到c1里,释放c2。

c1.merge(c2,comp)      合并2个有序的链表并使之按照自定义规则排序之后从新放到c1中,释放c2。

复制代码
 1     list<int> a1{1,2,3},a2{4,5,6};
 2     a1.merge(a2);
 3     list<int>::iterator it;
 4     cout << "a1.merge(a2):";
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     a2.merge(a1,[](int n1,int n2){return n1>n2;});
11     cout << "a2.merge(a1,comp):";
12     for(it = a2.begin();it!=a2.end();it++){
13         cout << *it << " ";
14     }
15     cout << endl;
复制代码

c1.splice(c1.beg,c2)      将c2连接在c1的beg位置,释放c2

复制代码
1     list<int> a1{1,2,3},a2{4,5,6};
2     a1.splice(a1.begin(), a2);
3     list<int>::iterator it;
4     cout << "a1.merge(a2):";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
复制代码

c1.splice(c1.beg,c2,c2.beg)      将c2的beg位置的元素连接到c1的beg位置,并且在c2中施放掉beg位置的元素

复制代码
1     list<int> a1{1,2,3},a2{4,5,6};
2     a1.splice(a1.begin(), a2,++a2.begin());
3     list<int>::iterator it;
4     cout << "a1.merge(a2):";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
9     return 0;
复制代码

c1.splice(c1.beg,c2,c2.beg,c2.end)      将c2的[beg,end)位置的元素连接到c1的beg位置并且释放c2的[beg,end)位置的元素

复制代码
1     list<int> a1{1,2,3},a2{4,5,6};
2     a1.splice(a1.begin(),a2,a2.begin(),a2.end());
3     list<int>::iterator it;
4     cout << "a1.merge(a2):";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
9     return 0;
复制代码

remove(num)             删除链表中匹配num的元素。

复制代码
1     list<int> a1{1,2,3,4,5};
2     a1.remove(3);
3     list<int>::iterator it;
4     cout << "remove():";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
复制代码

remove_if(comp)       删除条件满足的元素,参数为自定义的回调函数。

复制代码
1     list<int> a1{1,2,3,4,5};
2     a1.remove_if([](int n){return n<3;});
3     list<int>::iterator it;
4     cout << "remove_if():";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
复制代码

reverse()       反转链表

复制代码
1     list<int> a1{1,2,3,4,5};
2     a1.reverse();
3     list<int>::iterator it;
4     cout << "reverse:";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
复制代码

unique()       删除相邻的元素

复制代码
1     list<int> a1{1,1,3,3,5};
2     a1.unique();
3     list<int>::iterator it;
4     cout << "unique:";
5     for(it = a1.begin();it!=a1.end();it++){
6         cout << *it << " ";
7     }
8     cout << endl;
9     return 0;
复制代码

c.sort()       将链表排序,默认升序

c.sort(comp)       自定义回调函数实现自定义排序

复制代码
 1     list<int> a1{1,3,2,5,4};
 2     a1.sort();
 3     list<int>::iterator it;
 4     cout << "sort():";
 5     for(it = a1.begin();it!=a1.end();it++){
 6         cout << *it << " ";
 7     }
 8     cout << endl;
 9     
10     a1.sort([](int n1,int n2){return n1>n2;});
11     cout << "sort(function point):";
12     for(it = a1.begin();it!=a1.end();it++){
13         cout << *it << " ";
14     }
15     cout << endl;
复制代码

string 成员函数大全

构造

string()//构造空字符串
string(const char* s);//拷贝s所指向的字符串序列
string(const char* s, size_t n);//拷贝s所指向的字符串序列的第n个到结尾的字符
string(size_t n, char c);//将字符c复制n次
string(const string& str);//拷贝构造函数
string(const string& str, size_t pos, size_t len = npos);//拷贝s中从pos位置起的len个字符,若npos>字符串长度,就拷贝到字符串结尾结束

析构

~string();//删除字符串

迭代器

/*迭代器*/
iterator begin(); //返回指向字符串第一个字符的迭代器
iterator end(); //返回指向字符串最后一个字符的下一个位置的迭代器
reverse_iterator rbegin(); //返回字符串最后一个字符的反向迭代器
reverse_iterator rend(); //返回指向字符串第一个字符之前的反向迭代器
/*常量迭代器*/
iterator cbegin(); //返回指向字符串第一个字符的迭代器
iterator cend(); //返回指向字符串最后一个字符的下一个位置的迭代器
reverse_iterator rcbegin(); //返回字符串最后一个字符的反向迭代器
reverse_iterator rcend(); //返回指向字符串第一个字符之前的反向迭代器

访问

reference at(size_type pos);//同char& operator[],返回pos位置字符的引用,字符串可读可写
char& back();//返回最后字符的引用
char& front();//返回第一个字符的引用

长度及容量

size_t size();//返回字符串字符个数
size_t length();//返回字符串字符个数
size_t max_size();//返回string对象中可存放的最大字符串的长度
size_t capacity();//返回string分配的存储容量。
void resize (size_t n);//调整源字符串的长度为n。
void resize (size_t n, char c);//调整字符串长度为n,并用字符c填充不足的部分
void reserve (size_t n = 0);//重新给源字符串分配存储最小为n的容量
void shrink_to_fit()//清理内存,使字符串的容量变得等于字符串的大小
void clear();//将字符串的内容清空,让源字符串成为一个空字符串(长度为0个字符)
bool empty();//判断字符串是否为空

修饰

1. append() 在结尾添加字符串

string & append(const string & str)//在结尾添加一个string字符串
string & append(const string & str, size_type subpos, size_type sublen)//追加str中从subpos开始的sublen个字符(子串)
string & append(const charT * s)//C语言字符串
string & append(const charT * s, size_type n)//C语言字符串(长度为n的子串)
string & append(size_type n, charT c)//n个字符c
string & append(InputIterator first, InputIterator last)//使用迭代器append

2. push_back 将字符添加到串尾

void push_back (charT c);//将字符C添加到结尾

3. assign 赋值

string &assign(const char *s);///char*类型的字符串赋给当前字符串
string &assign(const char *s,int n);//用c字符串s开始的n个字符赋值
string &assign(const string &s);//把字符串s赋给当前字符串
string &assign(int n,char c);//用n个字符c赋值给当前字符串
string &assign(const string &s,int start,int n);//把字符串s中从start开始的n个字符赋给当前字符串
string &assign(const_iterator first,const_itertor last);//把first和last迭代器之间的部分赋给字符串

4. insert 在串中间插入#

string & insert(size_type pos, const string & str)//在pos位置插入字符串str
string & insert(size_type pos, const string & str,size_type subpos, size_type sublen)//从subpos开始的sublen的子串
string & insert(size_type pos, const charT * s)//C语言字符串
string & insert(size_type pos, const charT * s, size_type n)//C语言字符串(长度为n的子串)
string & insert(size_type pos,   size_type n, charT c)//n个字符c
iterator insert(const_iterator p, size_type n, charT c)//使用迭代器索引插入n和字符
iterator insert(const_iterator p, charT c)//单一字符
iterator insert(iterator p, InputIterator first, InputIterator last)//使用迭代器insert

5. erase 删除字符串中的特定字符

string & erase(size_type pos=0, size_type len=npos)//从pos处删除len长度的字符
iterator erase(const_iterator p)//删除迭代器所指的单一字符
iterator erase(const_iterator first, const_iterator last)//删除2迭代器中间的字符

6. replace 替换字符串的一部分

string & replace(size_type pos,size_type len,const string & str)//从pos位置开始,长度为len的字符替换为str
string & replace(const_iterator i1, const_iterator i2, const string & str)//替换两迭代器之间的字符
string & replace(size_type pos, size_type len, const string & str,size_type subpos, size_type sublen)//使用子串替换
string & replace(size_type pos,     size_type len,     const charT * s)//使用C语言字符串
string & replace(const_iterator i1, const_iterator i2, const charT * s)//迭代器方法
string & replace(size_type pos,     size_type len,     const charT * s, size_type n)//使用子串
string & replace(const_iterator i1, const_iterator i2, const charT * s, size_type n)//迭代器方法
string & replace(size_type pos,     size_type len,     size_type n, charT c)//用n个字符c替换
string & replace(const_iterator i1, const_iterator i2, size_type n, charT c)//迭代器方法
string & replace(const_iterator i1, const_iterator i2,
                       InputIterator first, InputIterator last)//迭代器方法

7. swap 交换2字符串

void swap (& str);//交换self和str

8. pop_back 删除最后一个字符

void pop_back();//删除串中最后一个字符

操作

1. C_str 转为C语言字符串

const charT* c_str() const;//返回C语言字符串常量,指向以空字符终止的数组

2. data 转为C语言字符数组

const charT* data() const;//返回C语言字符串常量,结尾没有'\0'

3. get_allocator 用于分配内存的内存块

allocator_type get_allocator() const;//它返回与容器关联的分配器对象的副本。yongy

4.copy 复制到字符数组

size_type copy (charT* s, size_type len, size_type pos = 0) const;//从string类型对象中至多复制n个字符到字符指针p指向的空间中。不添加'\0'

5. find 查找

size_type find(const string & str, size_type pos=0) const;//从母字符串的pos位置查找字串str.存在返回字串第一个字符的位置,不存在返回npos
size_type find(const charT * s, size_type pos=0) const;//C语言字符串作为子串
size_type find(const charT * s, size_type pos, size_type n) const;//C语言字符串的子串(长度为n)作为被查找子串
size_type find(charT c, size_type pos=0) const;//查找单个字符
//倒着找
size_type rfind(const string & str, size_type pos=npos) const;
size_type rfind(const charT * s, size_type pos=npos);
size_type rfind(const charT * s, size_type pos, size_type n);
size_type rfind(charT c, size_type pos=npos) const;
//查找字符串中与目标字符(串中任一个字符)相同的第一个字符
size_type find_first_of(const string & str, size_type pos=0) const;
size_type find_first_of(const charT * s, size_type pos=0) const;
size_type find_first_of(const charT * s, size_type pos, size_type n);
size_type find_first_of(charT c, size_type pos=0) const;
//倒着找 or 找最后一个
size_type find_last_of(const string & str, size_type pos=npos) const 
size_type find_last_of(const charT * s, size_type pos=npos) const
size_type find_last_of(const charT * s, size_type pos, size_type n) const
size_type find_last_of(charT c, size_type pos=npos) const
//查找字符串中与目标字符(串中任一个字符)不相同的第一个字符
size_type find_first_not_of(const string & str, size_type pos=0) const;
size_type find_first_not_of(const charT * s, size_type pos=0) const;
size_type find_first_not_of(const charT * s, size_type pos, size_type n) const;
size_type find_first_not_of(charT c, size_type pos=0) const;
//倒着找 or 找最后一个
size_type find_last_not_of(const string & str, size_type pos=npos) const ;
size_type find_last_not_of(const charT * s, size_type pos=npos) const;
size_type find_last_not_of(const charT * s, size_type pos, size_type n) const;
size_type find_last_not_of(charT c, size_type pos=npos) const ;

6. substr 子串

string substr (size_type pos = 0, size_type len = npos) const;//返回一个从pos开始,len长度的string类型的子串

7.compare 比较

int compare (const string& str) const ;//比较字符串大小,源串大于str返回值>0,相同=0,小于<0
int compare (size_type pos, size_type len, const string& str) const;//用自身的子串比较
int compare (size_type pos, size_type len, const string& str,
             size_type subpos, size_type sublen) const;//两字符串均为子串
int compare (const charT* s) const;//C语言字符串
int compare (size_type pos, size_type len, const charT* s) const;//C语言字符串子串
int compare (size_type pos, size_type len, const charT* s, size_type n) const;//双子串

二、符号重载

1. = 赋值#

Copy
string &operator=(const string &s);//把字符串s赋给当前字符串
string &operator=(const char* s);//char*类型的字符串赋给当前字符串
string &operator=(char c);//单个字符赋给当前字符串

2. [] 访问#

Copy
char& operator[] (size_t pos);//返回pos处字符的引用 越界导致未定义行为

3. += 追加#

Copy
string& operator+= (const string& str);//在结尾加如str字符串,等效于append
string& operator+= (const char* s);//C语言字符串
string& operator+= (char c);//单个字符

三、非成员函数重载

函数/操作   作用
+   合并两个字符串
==,>=,<=,!=,>,<   比较字符串大小
>>,<<   加入输入输出流,用于输入/输出
getline   读取一行,存储在字符串中
posted @ 2022-07-28 09:53  Doria_tt  阅读(75)  评论(0)    收藏  举报