C++ STL

释放双眼,带上耳机,听听看~!

C++ STL中最基本以及最常用的类或容器无非就是以下几个:

string
vector
set
list
map
下面就依次介绍它们,并给出一些最常见的最实用的使用方法,做到快速入门。

string

首先看看我们C语言一般怎么使用字符串的


1
2
3
4
5
6
7
8
9
10
11
1char* s1 = "Hello SYSU!"; //创建指针指向字符串常量,这段字符串我们是不能修改的
2
3//想要创建 可以修改的字符串,我们可以使用数组分配空间
4char s2[20] = "Hello SYSU!";
5//或者这样
6char s3[] = "Hello SYSU!";
7
8//当然我们也可以动态分配内存
9char* s4 = (char*)malloc(20);
10gets(s4);
11

C++ 标准库中的string表示可变长的字符串,它在头文件#include <string>里面。
用string初始化字符串分两类:用“=”号就是拷贝初始化,否则就是直接初始化。
C++ STL


1
2
3
4
5
6
7
8
1string s1;//初始化字符串,空字符串
2string s2 = s1; //拷贝初始化,深拷贝字符串
3string s3 = &quot;I am Yasuo&quot;; //直接初始化,s3存了字符串
4string s4(10, &#x27;a&#x27;); //s4存的字符串是aaaaaaaaaa
5string s5(s4); //拷贝初始化,深拷贝字符串
6string s6(&quot;I am Ali&quot;); //直接初始化
7string s7 = string(6, &#x27;c&#x27;); //拷贝初始化,cccccc
8

C++ STL


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1#include &lt;iostream&gt;
2#include &lt;string&gt;
3
4using namespace std;
5
6int main()
7{
8    string s1;//初始化字符串,空字符串
9    string s2 = s1; //拷贝初始化,深拷贝字符串
10    string s3 = &quot;I am Yasuo&quot;; //直接初始化,s3存了字符串
11    string s4(10, &#x27;a&#x27;); //s4存的字符串是aaaaaaaaaa
12    string s5(s4); //拷贝初始化,深拷贝字符串
13    string s6(&quot;I am Ali&quot;); //直接初始化
14    string s7 = string(6, &#x27;c&#x27;); //拷贝初始化,cccccc
15
16    //string的各种操作
17    string s8 = s3 + s6;//将两个字符串合并成一个
18    s3 = s6;//用一个字符串来替代另一个字符串的对用元素
19
20    cin &gt;&gt; s1;
21
22    cout &lt;&lt; s1 &lt;&lt; endl;
23    cout &lt;&lt; s2 &lt;&lt; endl;
24    cout &lt;&lt; s3 &lt;&lt; endl;
25    cout &lt;&lt; s4 &lt;&lt; endl;
26    cout &lt;&lt; s5 &lt;&lt; endl;
27    cout &lt;&lt; s6 &lt;&lt; endl;
28    cout &lt;&lt; s7 &lt;&lt; endl;
29    cout &lt;&lt; s8 &lt;&lt; endl;
30    cout &lt;&lt; &quot;s7 size = &quot; &lt;&lt; s7.size() &lt;&lt; endl; //字符串长度,不包括结束符
31    cout &lt;&lt; (s2.empty() ? &quot;This string is empty&quot; : &quot;This string is not empty&quot;) &lt;&lt; endl;;
32
33    system(&quot;pause&quot;);
34    return 0;
35}
36

C++ STL
string的IO操作
使用cin读入字符串时,遇到空白就停止读取。比如程序输入的是
" Hello World"
那么我们得到的字符串将是”Hello”,前面的空白没了,后面的world也读不出来。

如果我们想把整个hello world读进来怎么办?那就这样做
cin>>s1>>s2;
hello存在s1里,world存在s2里了。

有时我们想把一个句子存下来,又不想像上面那样创建多个string来存储单词,怎么办?

那就是用getline来获取一整行内容。


1
2
3
4
1string str;
2getline(cin, str);
3cout &lt;&lt; str &lt;&lt; endl;
4

当把string对象和字符面值及字符串面值混在一条语句中使用时,必须确保+的两侧的运算对象至少有一个是string


1
2
3
4
5
1string s1 = s2 + &quot;, &quot;; //正确
2string s3 = &quot;s &quot; + &quot;, &quot;; //错误
3string s4 = &quot;hello&quot; + &quot;, &quot; + s1; //错误
4string s5 = s1 + &quot;hello &quot; + &quot;, &quot;; //改一下顺序,s1放前头,正确了,注意理解=号右边的运算顺序
5

处理string中的字符

访问字符串的每个字符


1
2
3
4
5
6
1for (int i = 0; i &lt; s3.size(); i++)
2{
3    cout &lt;&lt; s3[i] &lt;&lt; endl;
4    s3[i] = &#x27;s&#x27;;
5}
6

在C语言中我都是用下标或者指针来访问数组元素,而在C++里,有个新奇的东西叫做迭代器iterator,我们可以使用它来访问容器元素。
C++ STL


1
2
3
4
5
6
1string str(&quot;hi sysu&quot;);
2for (string::iterator it = str.begin(); it != str.end(); it++)
3{
4    cout &lt;&lt; *it &lt;&lt; endl;
5}
6

我们也可以是使用const_iterator使得访问元素时是能读不能写,这跟常量指针意思差不多。


1
2
3
4
5
6
7
1string str2(&quot;hi sysu&quot;);
2for (string::const_iterator it = str2.begin(); it != str2.end(); it++)
3{
4    cout &lt;&lt; *it &lt;&lt; endl;
5    *it = &#x27;l&#x27;; //这是错误的,不能写
6}
7

C++ STL

string还有一些很好用的函数,比如找子串


1
2
3
4
5
6
7
1string sq(&quot;heoolo sdaa ss&quot;);
2cout &lt;&lt; s.find(&quot;aa&quot;, 0) &lt;&lt; endl; //返回的是子串位置。第二个参数是查找的起始位置,如果找不到,就返回string::npos
3if (s.find(&quot;aa1&quot;, 0) == string::npos)
4{
5    cout &lt;&lt; &quot;找不到该子串!&quot; &lt;&lt; endl;
6}
7

vector

向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

C++ STL中的verctor好比是C语言中的数组,但是vector又具有数组没有的一些高级功能。与数组相比,vector就是一个可以不用再初始化就必须制定大小的边长数组,当然了,它还有许多高级功能。

要想用vector首先得包含头文件vector。

#include <vector>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1二、容器特性
21.顺序序列
3顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
4
52.动态数组
6支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。
7
83.能够感知内存分配器的(Allocator-aware)
9容器使用一个内存分配器对象来动态地处理它的存储需求。
10
11三、基本函数实现
121.构造函数
13vector():创建一个空vector
14vector(int nSize):创建一个vector,元素个数为nSize
15vector(int nSize,const t&amp; t):创建一个vector,元素个数为nSize,且值均为t
16vector(const vector&amp;):复制构造函数
17vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
182.增加函数
19void push_back(const T&amp; x):向量尾部增加一个元素X
20iterator insert(iterator it,const T&amp; x):向量中迭代器指向元素前增加一个元素x
21iterator insert(iterator it,int n,const T&amp; x):向量中迭代器指向元素前增加n个相同的元素x
22iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据
233.删除函数
24iterator erase(iterator it):删除向量中迭代器指向元素
25iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
26void pop_back():删除向量中最后一个元素
27void clear():清空向量中所有元素
284.遍历函数
29reference at(int pos):返回pos位置元素的引用
30reference front():返回首元素的引用
31reference back():返回尾元素的引用
32iterator begin():返回向量头指针,指向第一个元素
33iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
34reverse_iterator rbegin():反向迭代器,指向最后一个元素
35reverse_iterator rend():反向迭代器,指向第一个元素之前的位置
365.判断函数
37bool empty() const:判断向量是否为空,若为空,则向量中无元素
386.大小函数
39int size() const:返回向量中元素的个数
40int capacity() const:返回当前向量张红所能容纳的最大元素值
41int max_size() const:返回最大可允许的vector元素数量值
427.其他函数
43void swap(vector&amp;):交换两个同类型向量的数据
44void assign(int n,const T&amp; x):设置向量中第n个元素的值为x
45void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素
468.看着清楚
471.push_back 在数组的最后添加一个数据
48
492.pop_back 去掉数组的最后一个数据
50
513.at 得到编号位置的数据
52
534.begin 得到数组头的指针
54
555.end 得到数组的最后一个单元+1的指针
56
576.front 得到数组头的引用
58
597.back 得到数组的最后一个单元的引用
60
618.max_size 得到vector最大可以是多大
62
639.capacity 当前vector分配的大小
64
6510.size 当前使用数据的大小
66
6711.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
68
6912.reserve 改变当前vecotr所分配空间的大小
70
7113.erase 删除指针指向的数据项
72
7314.clear 清空当前的vector
74
7515.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)
76
7716.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)
78
7917.empty 判断vector是否为空
80
8118.swap 与另一个vector交换数据
82

C++ STL
如果vector的元素类型是int,默认初始化为0;如果vector元素类型为string,则默认初始化为空字符串。


1
2
3
4
5
6
7
8
9
10
11
1vector&lt;int&gt; v1;
2vector&lt;father&gt; v2;
3vector&lt;string&gt; v3;
4vector&lt;vector&lt;int&gt; &gt;;  //注意空格。这里相当于二维数组int a[n][n];
5vector&lt;int&gt; v5 = { 1,2,3,4,5 }; //列表初始化,注意使用的是花括号
6vector&lt;string&gt; v6 = { &quot;hi&quot;,&quot;my&quot;,&quot;name&quot;,&quot;is&quot;,&quot;lee&quot; };
7vector&lt;int&gt; v7(5, -1); //初始化为-1,-1,-1,-1,-1。第一个参数是数目,第二个参数是要初始化的值
8vector&lt;string&gt; v8(3, &quot;hi&quot;);
9vector&lt;int&gt; v9(10); //默认初始化为0
10vector&lt;int&gt; v10(4); //默认初始化为空字符串
11

C++ STL
C++ STL

请使用push_back加入元素,并且这个元素是被加在数组尾部的。


1
2
3
4
5
1for (int i = 0; i &lt; 20; i++)
2{
3    v1.push_back(i);
4}
5

访问和操作vector中的每个元素


1
2
3
4
5
6
7
1for (int i = 0; i &lt; v1.size(); i++)
2{
3    cout &lt;&lt; v1[i] &lt;&lt; endl;
4    v1[i] = 100;
5    cout &lt;&lt; v1[i] &lt;&lt; endl;
6}
7

注意:只能对已存在的元素进行赋值或者修改操作,如果是要加入新元素,务必使用push_back。push_back的作用有两个:告诉编译器为新元素开辟空间、将新元素存入新空间里。

比如下面的代码是错误的,但是编译器不会报错,就像是数组越界。
vector<int> vec;
vec[0] = 1; //错误!
当然我们也可以选择使用迭代器来访问元素


1
2
3
4
5
6
7
8
9
1vector&lt;string&gt; v6 = { &quot;hi&quot;,&quot;my&quot;,&quot;name&quot;,&quot;is&quot;,&quot;lee&quot; };
2for (vector&lt;string&gt;::iterator iter = v6.begin(); iter != v6.end(); iter++)
3{
4    cout &lt;&lt; *iter &lt;&lt; endl;
5    //下面两种方法都行
6    cout &lt;&lt; (*iter).empty() &lt;&lt; endl;
7    cout &lt;&lt; iter-&gt;empty() &lt;&lt; endl;
8}
9

上面是正向迭代,如果我们想从后往前迭代该如何操作?
使用反向迭代器


1
2
3
4
5
1for (vector&lt;string&gt;::reverse_iterator iter = v6.rbegin(); iter != v6.rend(); iter++)
2{
3    cout &lt;&lt; *iter &lt;&lt; endl;
4}
5

实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1#include &lt;iostream&gt;
2#include &lt;vector&gt;
3#include &lt;string&gt;
4
5using namespace std;
6
7template &lt;typename T&gt;
8void showvector(vector&lt;T&gt; v)
9{
10    for (vector&lt;T&gt;::iterator it = v.begin(); it != v.end(); it++)
11    {
12        cout &lt;&lt; *it;
13    }
14    cout &lt;&lt; endl;
15}
16
17int main()
18{
19    vector&lt;string&gt; v6 = { &quot;hi&quot;,&quot;my&quot;,&quot;name&quot;,&quot;is&quot;,&quot;lee&quot; };
20    v6.resize(3);  //重新调整vector容量大小
21    showvector(v6);
22
23    vector&lt;int&gt; v5 = { 1,2,3,4,5 }; //列表初始化,注意使用的是花括号
24    cout &lt;&lt; v5.front() &lt;&lt; endl; //访问第一个元素
25    cout &lt;&lt; v5.back() &lt;&lt; endl; //访问最后一个元素
26
27    showvector(v5);
28    v5.pop_back(); //删除最后一个元素
29    showvector(v5);
30    v5.push_back(6); //加入一个元素并把它放在最后
31    showvector(v5);
32    v5.insert(v5.begin()+1,9); //在第二个位置插入新元素
33    showvector(v5);
34    v5.erase(v5.begin() + 3);  //删除第四个元素
35    showvector(v5);
36    v5.insert(v5.begin() + 1, 7,8); //连续插入7个8
37    showvector(v5);
38    v5.clear(); //清除所有内容
39    showvector(v5);
40
41    system(&quot;pause&quot;);
42    return 0;
43}
44

C++ STL
注意:虽然vertor对象可以动态增长,但是也或有一点副作用:已知的一个限制就是不能再范围for循环中向vector对象添加元素。另外一个限制就是任何一种可能改变vector对象容量的操作,不如push_back,都会使该迭代器失效。

总而言之就是:但凡使用了迭代器的循环体,都不要向迭代器所属的容器添加元素!

C++中push_back和insert两个有什么区别?

顾名思义push_back把元素插入容器末尾,insert把元素插入任何你指定的位置。
不过push_back速度一般比insert快。如果能用push_back尽量先用push_back。

1.pop_back()&push_back(elem)实例在容器最后移除和插入数据


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
1#include &lt;string.h&gt; 
2#include &lt;vector&gt;
3#include &lt;iostream&gt;
4using namespace std;
5
6int main()
7{
8    vector&lt;int&gt;obj(10,0);//最大容器为10,都初始化为0
9    for(int i=0;i&lt;10;i++)//push_back(elem)在数组最后添加数据
10    {
11        obj.push_back(i);
12        cout&lt;&lt;obj[i]&lt;&lt;&quot;,&quot;;
13    }
14
15    for(int i=0;i&lt;5;i++)//去掉数组最后一个数据
16    {
17        obj.pop_back();
18    }
19
20    cout&lt;&lt;&quot;\n&quot;&lt;&lt;endl;
21
22    for(int i=0;i&lt;obj.size();i++)//size()容器中实际数据个数
23    {
24        cout&lt;&lt;obj[i]&lt;&lt;&quot;,&quot;;
25    }
26
27    return 0;
28}
29

1
2
3
4
5
6
1输出结果为:
2
30,1,2,3,4,5,6,7,8,9,
4
50,1,2,3,4,
6

2.clear()清除容器中所以数据


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1#include &lt;string.h&gt;
2#include &lt;vector&gt;
3#include &lt;iostream&gt;
4using namespace std;
5
6int main()
7{
8    vector&lt;int&gt;obj;
9    for(int i=0;i&lt;10;i++)//push_back(elem)在数组最后添加数据
10    {
11        obj.push_back(i);
12        cout&lt;&lt;obj[i]&lt;&lt;&quot;,&quot;;
13    }
14
15    obj.clear();//清除容器中所以数据
16    for(int i=0;i&lt;obj.size();i++)
17    {
18        cout&lt;&lt;obj[i]&lt;&lt;endl;
19    }
20
21    return 0;
22}
23

1
2
3
4
1输出结果为:
2
30,1,2,3,4,5,6,7,8,9,
4

3.排序


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
1#include &lt;string.h&gt;
2#include &lt;vector&gt;
3#include &lt;iostream&gt;
4#include &lt;algorithm&gt;
5using namespace std;
6
7int main()
8{
9    vector&lt;int&gt;obj;
10
11    obj.push_back(1);
12    obj.push_back(3);
13    obj.push_back(0);
14
15    sort(obj.begin(),obj.end());//从小到大
16
17    cout&lt;&lt;&quot;从小到大:&quot;&lt;&lt;endl;
18    for(int i=0;i&lt;obj.size();i++)
19    {
20        cout&lt;&lt;obj[i]&lt;&lt;&quot;,&quot;;  
21    }
22
23    cout&lt;&lt;&quot;\n&quot;&lt;&lt;endl;
24
25    cout&lt;&lt;&quot;从大到小:&quot;&lt;&lt;endl;
26    reverse(obj.begin(),obj.end());//从大到小
27    for(int i=0;i&lt;obj.size();i++)
28    {
29        cout&lt;&lt;obj[i]&lt;&lt;&quot;,&quot;;
30    }
31    return 0;
32}
33

1
2
3
4
5
6
7
8
1输出结果为:
2
3从小到大:
40,1,3,
5
6从大到小:
73,1,0,
8

1.注意 sort 需要头文件 #include

2.如果想 sort 来降序,可重写 sort


1
2
3
4
5
6
7
8
9
1bool compare(int a,int b)
2{
3    return a&lt; b; //升序排列,如果改为return a&gt;b,则为降序
4}
5int a[20]={2,4,1,23,5,76,0,43,24,65},i;
6for(i=0;i&lt;20;i++)
7    cout&lt;&lt; a[i]&lt;&lt; endl;
8sort(a,a+20,compare);
9

4.访问(直接数组访问&迭代器访问)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1#include &lt;string.h&gt;
2#include &lt;vector&gt;
3#include &lt;iostream&gt;
4#include &lt;algorithm&gt;
5using namespace std;
6
7int main()
8{
9    //顺序访问
10    vector&lt;int&gt;obj;
11    for(int i=0;i&lt;10;i++)
12    {
13        obj.push_back(i);  
14    }
15
16    cout&lt;&lt;&quot;直接利用数组:&quot;;
17    for(int i=0;i&lt;10;i++)//方法一
18    {
19        cout&lt;&lt;obj[i]&lt;&lt;&quot; &quot;;
20    }
21
22    cout&lt;&lt;endl;
23    cout&lt;&lt;&quot;利用迭代器:&quot; ;
24    //方法二,使用迭代器将容器中数据输出
25    vector&lt;int&gt;::iterator it;//声明一个迭代器,来访问vector容器,作用:遍历或者指向vector容器的元素
26    for(it=obj.begin();it!=obj.end();it++)
27    {
28        cout&lt;&lt;*it&lt;&lt;&quot; &quot;;
29    }
30    return 0;
31}
32

5.二维数组两种定义方法(结果一样)


1
2
3
4
5
1输出结果为:
2
3直接利用数组:0 1 2 3 4 5 6 7 8 9
4利用迭代器:0 1 2 3 4 5 6 7 8 9
5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1方法一
2#include &lt;string.h&gt;
3#include &lt;vector&gt;
4#include &lt;iostream&gt;
5#include &lt;algorithm&gt;
6using namespace std;
7
8
9int main()
10{
11    int N=5, M=6;
12    vector&lt;vector&lt;int&gt; &gt; obj(N); //定义二维动态数组大小5行
13    for(int i =0; i&lt; obj.size(); i++)//动态二维数组为5行6列,值全为0
14    {
15        obj[i].resize(M);
16    }
17
18    for(int i=0; i&lt; obj.size(); i++)//输出二维动态数组
19    {
20        for(int j=0;j&lt;obj[i].size();j++)
21        {
22            cout&lt;&lt;obj[i][j]&lt;&lt;&quot; &quot;;
23        }
24        cout&lt;&lt;&quot;\n&quot;;
25    }
26    return 0;
27}
28
29方法二
30#include &lt;string.h&gt;
31#include &lt;vector&gt;
32#include &lt;iostream&gt;
33#include &lt;algorithm&gt;
34using namespace std;
35
36
37int main()
38{
39    int N=5, M=6;
40    vector&lt;vector&lt;int&gt; &gt; obj(N, vector&lt;int&gt;(M)); //定义二维动态数组5行6列
41
42    for(int i=0; i&lt; obj.size(); i++)//输出二维动态数组
43    {
44        for(int j=0;j&lt;obj[i].size();j++)
45        {
46            cout&lt;&lt;obj[i][j]&lt;&lt;&quot; &quot;;
47        }
48        cout&lt;&lt;&quot;\n&quot;;
49    }
50    return 0;
51}
52输出结果为:
53
540 0 0 0 0 0
550 0 0 0 0 0
560 0 0 0 0 0
570 0 0 0 0 0
580 0 0 0 0 0
59

set

set跟vector差不多,它跟vector的唯一区别就是,set里面的元素是有序的且唯一的,只要你往set里添加元素,它就会自动排序,而且,如果你添加的元素set里面本来就存在,那么这次添加操作就不执行。要想用set先加个头文件set。
#include <set>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1#include &lt;iostream&gt;
2#include &lt;set&gt;
3#include &lt;string&gt;
4
5using namespace std;
6
7template &lt;typename T&gt;
8void showset(set&lt;T&gt; v)
9{
10    for (set&lt;T&gt;::iterator it = v.begin(); it != v.end(); it++)
11    {
12        cout &lt;&lt; *it;
13    }
14    cout &lt;&lt; endl;
15}
16
17int main()
18{
19    set&lt;int&gt; s1{9,8,1,2,3,4,5,5,5,6,7,7 }; //自动排序,从小到大,剔除相同项
20    showset(s1);
21    set&lt;string&gt; s2{ &quot;hello&quot;,&quot;sysy&quot;,&quot;school&quot;,&quot;hello&quot; }; //字典序排序
22    showset(s2);
23    s1.insert(9); //有这个值了,do nothing
24    showset(s1);
25    s2.insert(&quot;aaa&quot;); //没有这个字符串,添加并且排序
26    showset(s2);
27
28    system(&quot;pause&quot;);
29    return 0;
30}
31

C++ STL

set的各成员函数列表如下:

c++ stl容器set成员函数:begin()–返回指向第一个元素的迭代器

c++ stl容器set成员函数:clear()–清除所有元素

c++ stl容器set成员函数:count()–返回某个值元素的个数

c++ stl容器set成员函数:empty()–如果集合为空,返回true

c++ stl容器set成员函数:end()–返回指向最后一个元素的迭代器

c++ stl容器set成员函数:equal_range()–返回集合中与给定值相等的上下限的两个迭代器

c++ stl容器set成员函数:erase()–删除集合中的元素

c++ stl容器set成员函数:find()–返回一个指向被查找到元素的迭代器

c++ stl容器set成员函数:get_allocator()–返回集合的分配器

c++ stl容器set成员函数:insert()–在集合中插入元素

c++ stl容器set成员函数:lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器

c++ stl容器set成员函数:key_comp()–返回一个用于元素间值比较的函数

c++ stl容器set成员函数:max_size()–返回集合能容纳的元素的最大限值

c++ stl容器set成员函数:rbegin()–返回指向集合中最后一个元素的反向迭代器

c++ stl容器set成员函数:rend()–返回指向集合中第一个元素的反向迭代器

c++ stl容器set成员函数:size()–集合中元素的数目

c++ stl容器set成员函数:swap()–交换两个集合变量

c++ stl容器set成员函数:upper_bound()–返回大于某个值元素的迭代器

c++ stl容器set成员函数:value_comp()–返回一个用于比较元素间的值的函数

常用操作:
1.元素插入:insert()
2.中序遍历:类似vector遍历(用迭代器)
3.反向遍历:利用反向迭代器reverse_iterator。
例:


1
2
3
4
5
11 set&lt;int&gt; s;
22 ......
33 set&lt;int&gt;::reverse_iterator rit;
44 for(rit=s.rbegin();rit!=s.rend();rit++)
5

4.元素删除:与插入一样,可以高效的删除,并自动调整使红黑树平衡。


1
2
3
4
11 set&lt;int&gt; s;
22 s.erase(2);        //删除键值为2的元素
33 s.clear();
4

5.元素检索:find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。


1
2
3
4
5
6
7
8
1set&lt;int&gt; s;
2set&lt;int&gt;::iterator it;
3it = s.find(5);    //查找键值为5的元素
4if (it != s.end())    //找到
5cout &lt;&lt; *it &lt;&lt; endl;
6else            //未找到
7cout &lt;&lt; &quot;未找到&quot;;
8

6.自定义比较函数
(1)元素不是结构体:
例:
//自定义比较函数myComp,重载“()”操作符


1
2
3
4
5
6
7
8
9
10
1struct myComp
2{
3    bool operator()(const your_type &amp;a, const your_type &amp;b){
4        return a.data - b.data &gt; 0;
5    }
6}
7set&lt;int, myComp&gt;s;
8......
9set&lt;int, myComp&gt;::iterator it; erator it;
10

(2)如果元素是结构体,可以直接将比较函数写在结构体内。
例:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1struct Info
2{
3    string name;
4    float score;
5    //重载“&lt;”操作符,自定义排序规则
6    bool operator &lt; (const Info &amp;a) const
7    {
8        //按score从大到小排列
9        return a.score&lt;score;
10    }
11}
12set&lt;Info&gt; s;
13......
14set&lt;Info&gt;::iterator it;
15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1#include&lt;iostream&gt;
2#include&lt;set&gt;
3using namespace std;
4//set插入元素操作  
5int main()
6{
7    //定义一个int型集合对象s,当前没有任何元素.由www.169it.com搜集整理
8    set&lt;int&gt; s;
9    s.insert(8);  //第一次插入8,可以插入  
10    s.insert(1);
11    s.insert(12);
12    s.insert(6);
13    s.insert(8);   //第二次插入8,重复元素,不会插入  
14    set&lt;int&gt;::iterator it; //定义前向迭代器
15    for(it=s.begin();it!=s.end();it++)
16    cout&lt;&lt;*it&lt;&lt;endl;    
17    system(&quot;pause&quot;);
18    return 0;
19}
20

对于集合来说,我们一般有并集、交集、差集、补集这几种操作,所以在set的操作中我们也有类似的集合操作,它们都在#include的头文件下:

std::set_intersection() :这个函数是求两个集合的交集。
std::set_union() :求两个集合的并集
std::set_difference():差集
std::set_symmetric_difference(): 取集合对称差集

其中,关于函数的五个参数问题做一下小结:

1、这几个函数的前四个参数一样,只有第五个参数有多重版本。

2、EX1:set_union(A.begin(),A.end(),B.begin(),B.end(),inserter( C1 , C1.begin() ) );前四个参数依次是第一的集合的头尾,第二个集合的头尾。第五个参数的意思是将集合A、B取合集后的结果存入集合C中。

EX2:set_union(A.begin(),A.end(),B.begin(),B.end(),ostream_iterator(cout,” “));这里的第五个参数的意思是将A、B取合集后的结果直接输出,(cout,” “)双引号里面是输出你想用来间隔集合元素的符号或是空格。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
1#include &lt;iostream&gt;
2#include &lt;iterator&gt;
3#include &lt;set&gt;
4#include &lt;algorithm&gt;
5using namespace std;
6int main()
7{
8    set&lt;int&gt; eg1;
9    eg1.insert(1);
10    eg1.insert(100);
11    eg1.insert(5);
12    eg1.insert(1); //元素1因为已经存在所以set中不会再次插入1
13    eg1.insert(10);
14    eg1.insert(9);
15    //遍历set,可以发现元素是有序的
16    set&lt;int&gt;::iterator set_iter = eg1.begin();
17    cout &lt;&lt; &quot;Set named eg1:&quot; &lt;&lt; endl;
18    for (; set_iter != eg1.end(); set_iter++) cout &lt;&lt; *set_iter &lt;&lt; &quot; &quot;;
19    cout &lt;&lt; endl;
20    //使用size()函数可以获得当前元素个数
21    cout &lt;&lt; &quot;Now there are &quot; &lt;&lt; eg1.size() &lt;&lt; &quot; elements in the set eg1&quot; &lt;&lt; endl;
22    if (eg1.find(200) == eg1.end())//find()函数可以查找元素是否存在
23        cout &lt;&lt; &quot;200 isn&#x27;t in the set eg1&quot; &lt;&lt; endl;
24
25
26
27    set&lt;int&gt; eg2;
28    for (int i = 6; i &lt; 15; i++)
29        eg2.insert(i);
30    cout &lt;&lt; &quot;Set named eg2:&quot; &lt;&lt; endl;
31    for (set_iter = eg2.begin(); set_iter != eg2.end(); set_iter++)
32        cout &lt;&lt; *set_iter &lt;&lt; &quot; &quot;;
33    cout &lt;&lt; endl;
34
35    //获得两个set的并
36    set&lt;int&gt; eg3;
37    cout &lt;&lt; &quot;Union(两个set的并集):&quot;;
38    set_union(eg1.begin(),
39        eg1.end(),
40        eg2.begin(),
41        eg2.end(),
42        insert_iterator&lt;set&lt;int&gt; &gt;(eg3, eg3.begin())
43        );//注意第五个参数的形式
44    copy(eg3.begin(), eg3.end(), ostream_iterator&lt;int&gt;(cout, &quot; &quot;));
45    cout &lt;&lt; endl;
46
47    //获得两个set的交,注意进行集合操作之前接收结果的set要调用clear()函数清空一下
48    eg3.clear();
49    set_intersection(eg1.begin(),
50        eg1.end(),
51        eg2.begin(),
52        eg2.end(),
53        insert_iterator&lt;set&lt;int&gt; &gt;(eg3, eg3.begin())
54        );
55    cout &lt;&lt; &quot;Intersection:&quot;;
56    copy(eg3.begin(), eg3.end(), ostream_iterator&lt;int&gt;(cout, &quot; &quot;));
57    cout &lt;&lt; endl;
58
59    //获得两个set的差
60    eg3.clear();
61    set_difference(eg1.begin(),
62        eg1.end(), eg2.begin(),
63        eg2.end(),
64        insert_iterator&lt;set&lt;int&gt; &gt;(eg3, eg3.begin())
65        );
66    cout &lt;&lt; &quot;Difference:&quot;;
67    copy(eg3.begin(), eg3.end(), ostream_iterator&lt;int&gt;(cout, &quot; &quot;));
68    cout &lt;&lt; endl;
69
70    //获得两个set的对称差,也就是假设两个集合分别为A和B那么对称差为AUB-A∩B
71    eg3.clear();
72    set_symmetric_difference(eg1.begin(), eg1.end(), eg2.begin(), eg2.end(), insert_iterator&lt;set&lt;int&gt; &gt;(eg3, eg3.begin()));
73    copy(eg3.begin(), eg3.end(), ostream_iterator&lt;int&gt;(cout, &quot; &quot;));
74    cout &lt;&lt; endl;
75
76    return 0;
77}
78
79
80
81下面给出一个关键字类型为char*的示例代码
82
83#include&lt;iostream&gt;
84#include&lt;iterator&gt;
85#include&lt;set&gt;
86using namespace std;
87struct ltstr
88{
89    bool operator() (const char* s1, const char* s2) const
90    {
91        return strcmp(s1, s2) &lt; 0;
92    }
93};
94
95int main()
96{
97    const int N = 6;
98    const char* a[N] = { &quot;isomer&quot;, &quot;ephemeral&quot;, &quot;prosaic&quot;,
99        &quot;nugatory&quot;, &quot;artichoke&quot;, &quot;serif&quot; };
100    const char* b[N] = { &quot;flat&quot;, &quot;this&quot;, &quot;artichoke&quot;,
101        &quot;frigate&quot;, &quot;prosaic&quot;, &quot;isomer&quot; };
102
103    set&lt;const char*, ltstr&gt; A(a, a + N);
104    set&lt;const char*, ltstr&gt; B(b, b + N);
105    set&lt;const char*, ltstr&gt; C;
106
107    cout &lt;&lt; &quot;Set A: &quot;;
108    //copy(A.begin(), A.end(), ostream_iterator&lt;const char*&gt;(cout, &quot; &quot;));
109    set&lt;const char*, ltstr&gt;::iterator itr;
110    for (itr = A.begin(); itr != A.end(); itr++) cout &lt;&lt; *itr &lt;&lt; &quot; &quot;;
111    cout &lt;&lt; endl;
112    cout &lt;&lt; &quot;Set B: &quot;;
113    copy(B.begin(), B.end(), ostream_iterator&lt;const char*&gt;(cout, &quot; &quot;));
114    cout &lt;&lt; endl;
115
116    cout &lt;&lt; &quot;Union: &quot;;
117    set_union(A.begin(), A.end(), B.begin(), B.end(),
118        ostream_iterator&lt;const char*&gt;(cout, &quot; &quot;),
119        ltstr());
120    cout &lt;&lt; endl;
121
122    cout &lt;&lt; &quot;Intersection: &quot;;
123    set_intersection(A.begin(), A.end(), B.begin(), B.end(), ostream_iterator&lt;const char*&gt;(cout, &quot; &quot;), ltstr());
124    cout &lt;&lt; endl;
125    set_difference(A.begin(), A.end(), B.begin(), B.end(), inserter(C, C.begin()), ltstr());
126    cout &lt;&lt; &quot;Set C (difference of A and B): &quot;;
127    copy(C.begin(), C.end(), ostream_iterator&lt;const char*&gt;(cout, &quot; &quot;));
128    cout &lt;&lt; endl;
129    return 0;
130}
131
132其中的ltstr也可以这样定义
133class ltstr
134{
135public:
136    bool operator() (const char* s1, const char*s2)const
137    {
138        return strcmp(s1, s2) &lt; 0;
139    }
140};
141
142更加通用的应用方式那就是数据类型也是由用户自定义的类来替代,比较的函数自定义,甚至可以加上二级比较,比如首先按照总分数排序,对于分数相同的按照id排序,下面是示例代码
143
144#include&lt;set&gt;
145#include&lt;iostream&gt;
146using namespace std;
147struct
148{
149    int id;
150    int score;
151    string name;
152};
153struct compare
154{
155    bool operator()(const Entity&amp; e1, const Entity&amp; e2)const   {
156        if (e1.score &lt; e2.score) return true;
157        else
158        if (e1.score == e2.score)
159        if (e1.id &lt; e2.id) return true;
160
161        return false;
162    }
163};
164
165int main()
166{
167    set&lt;Entity, compare&gt;s_test;
168    Entity a, b, c;
169    a.id = 123; a.score = 90; a.name = &quot;bill&quot;;
170    b.id = 121; b.score = 85; b.name = &quot;mary&quot;;
171    c.id = 130; c.score = 85; c.name = &quot;jerry&quot;;
172    s_test.insert(a); s_test.insert(b); s_test.insert(c);
173    set&lt;Entity, compare&gt;::iterator itr;
174    cout &lt;&lt; &quot;Score List(ordered by score):\n&quot;;
175    for (itr = s_test.begin(); itr != s_test.end(); itr++)
176        cout &lt;&lt; itr-&gt;id &lt;&lt; &quot;---&quot; &lt;&lt; itr-&gt;name &lt;&lt; &quot;---&quot; &lt;&lt; itr-&gt;score &lt;&lt; endl;
177    return 0;
178}
179

list

list就是链表,在C语言中我们想使用链表都是自己去实现的,实现起来倒不难,但是如果有现成的高效的链表可以使用的话,我们就不需要重复造轮子了。STL就提供了list容器给我们。

list是一个双向链表,而单链表对应的容器则是foward_list。

list即双向链表的优点是插入和删除元素都比较快捷,缺点是不能随机访问元素。

初始化方式就大同小异了,跟vector基本一样。要想用list先加个头文件list。
#include <list>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1#include &lt;iostream&gt;
2#include &lt;list&gt;
3#include &lt;string&gt;
4
5using namespace std;
6
7template &lt;typename T&gt;
8void showlist(list&lt;T&gt; v)
9{
10    for (list&lt;T&gt;::iterator it = v.begin(); it != v.end(); it++)
11    {
12        cout &lt;&lt; *it;
13    }
14    cout &lt;&lt; endl;
15}
16
17int main()
18{
19    list&lt;int&gt; l1{ 1,2,3,4,5,5,6,7,7 };
20    showlist(l1);
21    list&lt;double&gt; l2;
22    list&lt;char&gt; l3(10);
23    list&lt;int&gt; l4(5, 10); //将元素都初始化为10
24    showlist(l4);
25
26
27    system(&quot;pause&quot;);
28    return 0;
29}
30

C++ STL
值得注意的是,list容器不能调用algorithm下的sort函数进行排序,因为sort函数要求容器必须可以随机存储,而list做不到。所以,list自己做了一个自己用的排序函数,用法如下:


1
2
3
1list&lt;int&gt; l1{ 8,5,7,6,1,2,3,4,5,5,6,7,7 };
2l1.sort();
3

map

map运用了哈希表地址映射的思想,也就是key-value的思想,来实现的。

首先给出map最好用也最最常用的用法例子,就是用字符串作为key去查询操作对应的value。

C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值。本文主要总结一下map基本用法和嵌套用法示例。

map基本用法

1 头文件
#include <map>

2 定义
map<int, int> my_Map; //注意这里的int和int可以是其他类型
或者是typedef map<int, int> MY_MAP;
MY_MAP my_Map;

3 插入数据
(1) my_Map[1] = 1;
(2) my_Map.insert(map<int, int>::value_type(2,2));
(3) my_Map.insert(pair<int,int>(3,3));
(4) my_Map.insert(make_pair<string,int>(4,4));

4 查找数据和修改数据


1
2
3
4
5
6
7
1 (1)    int i = my_Map[1];
2        my_Map[1]   =   i;
3  (2)   MY_MAP::iterator   my_Itr;
4        my_Itr.find(2);
5        int j = my_Itr-&gt;second;
6        my_Itr-&gt;second = j;
7

注意:

A.键本身是不能被修改的,除非删除。

B.不管键存不存在,比如my_Map[1] = i;,都会执行赋值操作。

5 删除数据
(1) my_Map.erase(my_Itr);
(2) my_Map.erase(3);

6 遍历数据
for (my_Itr=my_Map.begin(); my_Itr!=my_Map.end(); ++my_Itr) {}

7 其它方法
my_Map.size() :返回元素数目
my_Map.empty():判断是否为空
my_Map.clear():清空所有元素

二、嵌套用法

1.示例如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2    map&lt;int,map&lt;int,int&gt; &gt;multiMap; //对于这样的map嵌套定义,  
3    map&lt;int, int&gt; temp;    //定义一个map&lt;int, string&gt;变量,对其定义后在插入multiMap  
4    temp[9] = 9;  
5    temp[10] = 10;  
6    multiMap[10] = temp;  
7    multiMap[10][11]=11;  
8    multiMap[5][30]=30;  
9    map&lt;int,map&lt;int,int&gt; &gt;::iterator multitr;  // 以下是如何遍历本multiMap  
10    map&lt;int,int&gt;::iterator intertr;  
11    for(multitr=multiMap.begin();multitr!=multiMap.end();multitr++)  
12    {
13        for(intertr= multitr -&gt;second.begin(); intertr != multitr -&gt;second.end(); intertr ++)  
14            cout&lt;&lt; multitr -&gt;first&lt;&lt;&quot; &quot;&lt;&lt;intertr-&gt;first&lt;&lt;&quot; (&quot;&lt;&lt;intertr -&gt; second &lt;&lt;&quot;)&quot;&lt;&lt;endl;  
15    }
16

or


1
2
3
4
1map&lt;int,map&lt;int,int&gt;* &gt;multiMap;  
2map&lt;int, int&gt;* temp = new map&lt;int, int&gt;;  
3multiMap[10]=temp;  
4

这样动态new内存,就要记得delete,否则会有内存泄露,delete如下:


1
2
3
4
5
6
7
8
9
1
2map&lt;int, int&gt;* temp1;
3for(multitr=multiMap.begin();multitr!=multiMap.end();multitr++)  
4{
5    temp1 = multitr -&gt;second;
6        delete  temp1;
7        temp1 = NULL;
8}
9

例子:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1#include &lt;iostream&gt;
2#include &lt;map&gt;
3#include &lt;string&gt;
4
5using namespace std;
6
7void showmap(map&lt;string, int&gt; v)
8{
9    for (map&lt;string, int&gt;::iterator it = v.begin(); it != v.end(); it++)
10    {
11        cout &lt;&lt; it-&gt;first &lt;&lt; &quot;  &quot; &lt;&lt; it-&gt;second &lt;&lt; endl;  //注意用法,不是用*it来访问了。first表示的是key,second存的是value
12    }
13    cout &lt;&lt; endl;
14}
15
16int main()
17{
18    map&lt;string, int&gt; m1; //&lt;&gt;里的第一个参数表示key的类型,第二个参数表示value的类型
19    m1[&quot;Kobe&quot;] = 100;
20    m1[&quot;James&quot;] = 99;
21    m1[&quot;Curry&quot;] = 98;
22
23    string s(&quot;Jordan&quot;);
24    m1[s] = 90;
25
26    cout &lt;&lt; m1[&quot;Kobe&quot;] &lt;&lt; endl;
27    cout &lt;&lt; m1[&quot;Jordan&quot;] &lt;&lt; endl;
28    cout &lt;&lt; m1[&quot;Durant&quot;] &lt;&lt; endl; //不存在这个key,就显示0
29
30    m1.erase(&quot;Curry&quot;);//通过关键字来删除
31    showmap(m1);
32    m1.insert(pair&lt;string, int&gt;(&quot;Harris&quot;, 89)); //也可以通过insert函数来实现增加元素
33    showmap(m1);
34    m1.clear(); //清空全部
35
36
37    system(&quot;pause&quot;);
38    return 0;
39}
40

C++ STL


C\C++中计时、延时函数

头文件: #include <time.h>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1#include &lt;iostream&gt;
2#include &lt;time.h&gt;
3void timeConsume()
4{
5    double start,stop,durationTime;
6    start = clock();
7    /*
8
9    ...代码片段
10
11    */
12    stop = clock();
13
14    durationTime = ((double)(stop-start))/CLK_TCK;
15    cout &lt;&lt; &quot;程序耗时:&quot; &lt;&lt; durationTime &lt;&lt; &quot; s&quot; &lt;&lt; endl;
16}
17

给TA打赏
共{{data.count}}人
人已打赏
安全技术

详解Node.js API系列 Http模块(2) CNodejs爬虫实现

2021-12-21 16:36:11

安全技术

从零搭建自己的SpringBoot后台框架(二十三)

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索