0x00.前言

STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。其中本文包含stringvectordeque 三个容器知识。

0x01.string

string基本概念

本质:

  • string是C++风格的字符串,而string本质上是一个类

string与char * 的区别

  • char * 是一个指针
  • string是一个类,类内部封装了char*,管理这个字符串,是一个char * 型的容器

特点:

string类内部封装了很多成员方法
例如:findcopydeleterepalceinsert
string管理char *所分配的内存,因此不用担心复制越界与取值越界等

string构造函数

Constructor原型:

  • string(); 创建一个空字符串,如:string str;
    string(const char* s); 使用字符串s进行初始化
  • string(const string& str) 使用一个string对象初始化另一个string对象
  • string(int n,char c) 使用n个字符c初始化

代码块:

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
#include <iostream>
#include <string>
using namespace std;



void test01()
{
//默认构造
string s1;

//使用字符串s进行初始化
const char* str = "hello world";
string s2(str);
cout << "s2=" << s2 << endl;

//使用一个string对象初始化另一个string对象
string s3(s2);
cout << "s3=" << s3 << endl;

//使用n个字符c初始化string
string s4(10, 'a');
cout << "s4=" << s4 << endl;
}

int main() {
test01();
return 0;
}

小结:Constructor很多灵活使用即可。

string赋值操作

赋值的函数原型:

  • string& operator=(const char* s); char*类型字符串 赋值给当前的字符串
  • string& operator=(const string& s); 把字符串s赋值给当前的字符串
  • string& operator=(char c); 字符赋值给当前的字符串
  • string& assign(const char* s) 把字符串s赋给当前的字符串
  • string& assign(const char* s,int n); 把字符串s的前n个字符赋给当前的字符串
  • string& assign(const string& s); 把字符串s赋给当前字符串
  • string& assign(int n,char c); 用n个字符赋值给当前字符串

代码块:

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
#include <iostream>
#include <string>
using namespace std;

void test01()
{
string str1;
str1 = "hello world";
cout << "str1=" << str1 << endl;

string str2;
str2 = str1;
cout << "str2=" << str2 << endl;

string str3;
str3 = 'a';
cout << "str3=" << str3 << endl;

string str4;
str4.assign("Hello C++");
cout << "str4=" << str4 << endl;

string str5;
str5.assign("Hello C++", 5);
cout << "str5=" << str5 << endl;

string str6;
str6.assign(str5);
cout << "str6=" << str6 << endl;

string str7;
str7.assign(5, 'x');
cout << "str7=" << str7 << endl;
}

int main() {
test01();
return 0;
}

/*
结果:
str1=hello world
str2=hello world
str3=a
str4=Hello C++
str5=Hello
str6=Hello
str7=xxxxx
*/

小结:string中赋值方法很多,operator=()已经非常实用

string字符串拼接

函数原型:

  • string& operator+=(const char* str); 重载+=
  • string& operator+=(const char c); 重载+=
  • string& operator+=(const string& str); 重载+=
  • string& append(const char* s); 把字符串s连接到当前字符串结尾
  • string& append(const char*s, int n); 把字符串s的前n个字符连接到当前字符串结尾
  • string& append(const string&s); 同operator+=(const string& str)
  • string& append(const string &s,int pos,int n); 字符串s从pos开始的n个字符追加到原串结尾

代码块:

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
#include <iostream>
#include <string>
using namespace std;

void test()
{
string str1 = "我";
str1 += "爱玩游戏";
cout << "str1=" << str1 << endl;
str1 += ':';
cout << "str1=" << str1 << endl;

string str2 = "LOL DNF";
str1 += str2;
cout << "str1=" << str1 << endl;

string str3 = "I";
str3.append(" love ");
cout << "str3=" << str3 << endl;

str3.append("game abcde",4);
cout << "str3=" << str3 << endl;

str3.append(str2);
cout << "str3=" << str3 << endl;

//参数1 追加的原串 参数2 从原串的第几个下标开始截取 参数3 截取的字符个数
str3.append(str2, 3, 4);
cout << "str3=" << str3 << endl;

}

int main() {
test();
return 0;
}

/*
控制台输出:
str1=我爱玩游戏
str1=我爱玩游戏:
str1=我爱玩游戏:LOL DNF
str3=I love
str3=I love game
str3=I love gameLOL DNF
str3=I love gameLOL DNF DNF
*/

string查找与替换

函数原型:

  • int find(const string& str,int pos = 0) const; 查找str第一次出现位置,从pos从开始查找
  • int find(const char* s,int pos = 0) const; 查找s第一次出现的位置,从pos开始查找
  • int find(const char* s,int pos,int n) const; 从pos位置查找s的前n个字符第一次位置
  • int find(const char c,int pos = 0) const; 查找字符c第一次出现位置
  • int rfind(const string& str,int pos = npos) const; 查找str最后一次位置,从pos开始查找
  • int rfind(const char* s,int pos = npos) const; 查找s最后一次出现的位置,从pos开始查找
  • int rfind(const char* s,int pos,int n) const; 从pos位置查找前n个字符最后一次位置
  • int rfind(char c,int pos = 0) const; 查找字符c最后一次出现位置
  • string& replace(int pos,n,const string& str); 替换从pos开始n个字符为字符串str
  • string& replace(int pos,int n ,const char* s); 替换从pos开始的n个祝福为字符串s

代码块:

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
 #include <iostream>
#include <string>
using namespace std;

//查找
void testFind()
{
string str1 = "abcdefgde";

int pos = str1.find("de");
//int pos = str1.find("df");
if (pos == -1)
{
cout << "未找到字符串" << endl;
}
else {
cout << "找到字符串,pos = " << pos << endl;
}

//find与rfind的区别就是查找的方向不同
//find从头向尾
//rfind从尾向头


//rfind
pos = str1.rfind("de");
cout << "pos = " << pos << endl;


}


//替换
void testReplace()
{
string str1 = "abcdefg";

//从下标为1起的三个字符,整体代换为"1111"
str1.replace(1,3,"1111");

cout << "str1 = " << str1 << endl;
}


int main() {
cout << "查找:" << endl;
testFind();
cout << "----------" << endl;

cout << "替换:" << endl;
testReplace();
cout << "----------" << endl;
return 0;
}

/*
运行结果

查找:
找到字符串,pos = 3
pos = 7
----------
替换:
str1 = a1111efg
----------
*/

小结:

  • find查找是从首字符到末字符,rfind则相反
  • find找到字符串后返回查找的第一个字符位置,找不到返回-1
  • replace在替换时,要制定从哪个位置开始,多少个字符,以及要整体替换成的目标字符串

string字符串的比较

比较方式:

  • 字符串比较是按字符的ASCII码进行对比
  • 相等返回0
  • 大于返回1
  • 小于返回-1

函数原型:

  • int compare(const string& s) const; 与字符串s比较
  • int compare(const char* s) const; 与C风格字符串s比较

代码块:

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
#include <iostream>
#include <string>
using namespace std;

//字符串比较
void test01()
{
string str1 = "hello";
string str2 = "hello";

//str1 = "xello";
//str1 = "axllo";

if (0 == str1.compare(str2))
{
cout << "str1 等于 str2" << endl;
}
else if (1 == str1.compare(str2))
{
cout << "str1 大于 str2" << endl;
}
else if (-1 == str1.compare(str2))
{
cout << "str1 小于 str2" << endl;
}
}


int main() {
test01();
return 0;
}

小结:字符串比较最大的用处在于比较比较两个串是否相等, 而不是判断谁大谁小

string字符存取

string中单个字符存取方式:

  • char& opetarot[](int n); 通过[]方式取字符
  • char& at(int n); 通过at方法取字符

代码块:

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
#include <iostream>
#include <string>
using namespace std;

//string字符存取

void test01()
{
string str = "hello";

cout << "str = " << str << endl;

//read
//1、通过 [] 访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str[i] << " ";
}
cout << endl;

//2、通过at方法访问单个字符
for (int i = 0; i < str.size(); i++)
{
cout << str.at(i) << " ";
}
cout << endl;

//write
str[0] = 'x';
cout << "str = " << str << endl;

str.at(1) = 'x';
cout << "str = " << str << endl;


}

int main() {
test01();
return 0;
}

/*
运行结果:

str = hello
h e l l o
h e l l o
str = xello
str = xxllo
*/

string插入和删除

函数原型:

  • string& insert(int pos,const char* s); 插入字符串
  • stirng& insert(int pos,const string& str); 插入字符串
  • string& insert(int pos,int n,char = c); 在指定位置插入n个字符c
  • string& erase(int pos, int n = npos); 删除从pos开始的n个字符

代码块:

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
#include <iostream>
#include <string>
using namespace std;

//string插入与删除

void test01()
{
string str = "hello";

cout << "str = " << str << endl;

str.insert(1,"111");

cout << "str = " << str << endl;

str.erase(1, 3);

cout << "str = " << str << endl;
}


int main() {
test01();
return 0;
}

小结:插入与删除的起始下标都是从0开始

string子串

函数原型:

  • string substr(int pos = 0,int n = npos) const; 返回由pos开始的n个字符组成的字符串

代码块:

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
#include <iostream>
#include <string>
using namespace std;

void test01()
{
string str = "abcdef";

//从下标为参数1的位置开始截取共参数2个字符,返回截取字符串
string subStr = str.substr(1, 3);

cout << "subStr = "<< subStr << endl;
}


//实用操作
void test02()
{
string email = "zhuangsan@sina.com";

//从邮件地址中获取用户名信息
int pos = email.find("@");
string username = email.substr(0, pos);

cout << "username = " << username << endl;
}


int main() {
//test01();
test02();
return 0;
}

0x02.vector

vector基本概念

功能:

  • vector数据结构与数组非常相似,也被称作单端数组

vector与普通的数组的区别:

  • 不同之处在于数组是静态空间,而vector可以作为动态扩展

动态扩展:

  • 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间。
  • 含有rend(),begin(),insert(),rbegin(),end()等等方法
  • vector容器的迭代器是支持随机访问的迭代器

vector构造函数

constructor原型:

  • vector<T> v;
  • vector(v.begin(), v.end()); 将v[begin(),end())区间中的元素拷贝给本身
  • vector(n,elem); 构造函数将n个elem拷贝给本身
  • vector(const vector &vec); 拷贝构造函数

代码块:

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
#include <iostream>
#include <vector>
using namespace std;


void printVector(vector<int>v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
//默认构造
cout << "默认构造:" << endl;
vector<int>v1;

for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}

printVector(v1);

//通过区间的方式进行构造
cout << "通过区间的方式进行构造:" << endl;
vector<int>v2(v1.begin(), v1.end());
printVector(v2);

//n个elem方式构造
cout << "n个elem方式构造:" << endl;
vector<int>v3(10, 100);
printVector(v3);

//拷贝构造
cout << "拷贝构造:" << endl;
vector<int>v4(v3);
printVector(v4);
}

int main() {
test();
return 0;
}

小结:常用默认构造与拷贝构造

vector赋值操作

函数原型:

  • vector& operator=(const vector& vec); 重载等号操作符
  • assign(beg, end); 将[ beg , end )区间中的数据拷贝赋值给本身
  • assign(n,elem); 将n个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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 #include <iostream>
#include <vector>
using namespace std;

//vector赋值

void printVector(vector<int>& v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}

printVector(v1);

//赋值
//operator=
vector<int>v2;
v2 = v1;
printVector(v2);

//assign
vector<int>v3;
v3.assign(v2.begin(), v2.end());
printVector(v3);

//n个elem方式赋值
vector<int>v4;
v4.assign(10,100);
printVector(v4);

}

int main() {
test();
return 0;
}

vector容量与大小

函数原型:

  • empty(); 判断容器是否为空

  • capacity(); 容器的容量

  • size(); 返回容器中的元素个数

  • resize(int num); 重新指定容器的长度为num,若容器变长,则以默认值填充新位置

    ​ 若容器变短,则末尾超出容器长度的元素被删除

  • resize(int num, elem) 与上大致相同,不同在于,容器变长,则以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
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
#include <iostream>
#include <vector>
using namespace std;

void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);

if (v1.empty())
{
cout << "v1为空" << endl;
}
else
{
cout << "v1不为空" << endl;
cout << "v1的容量为" << v1.capacity() << endl;
cout << "v1的大小为" << v1.size() << endl;
}

//重新指定大小
v1.resize(15,100); //利用重载版本,可以用参数2指定填充值,默认为0
printVector(v1);
cout << "v1的容量为" << v1.capacity() << endl;
cout << "v1的大小为" << v1.size() << endl;

v1.resize(5);
printVector(v1);
cout << "v1的容量为" << v1.capacity() << endl;
cout << "v1的大小为" << v1.size() << endl;
}

int main() {
test();
return 0;
}

/*
运行结果:

0 1 2 3 4 5 6 7 8 9
v1不为空
v1的容量为13
v1的大小为10
0 1 2 3 4 5 6 7 8 9 100 100 100 100 100
v1的容量为19
v1的大小为15
0 1 2 3 4
v1的容量为19
v1的大小为5
*/

vector插入与删除

函数原型:

  • push_back(ele); 尾部插入元素ele
  • pop_back(); 删除最后一个元素
  • insert(const_iterator pos,ele); 迭代器指向位置pos插入元素ele
  • insert(const_iterator pos,int count,ele); 迭代器指向位置pos插入count个元素ele
  • ersae(const_iterator pos); 删除迭代器指向的元素
  • erase(const_iterator start,const_iterator end); 删除迭代器从start到end之间的元素
  • clear(); 删除容器中的所有元素

代码块:

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
#include <iostream>
#include <vector>
using namespace std;

void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
vector<int>v1;
for (int i = 1; i < 6; i++)
{
//尾插
v1.push_back(i*10);
}

//遍历
printVector(v1);

//尾删
v1.pop_back();
printVector(v1);

//插入 第一个参数是迭代器
v1.insert(v1.begin(), 100);
printVector(v1);

v1.insert(v1.begin(), 2, 1000);
printVector(v1);

//删除 参数也是迭代器
v1.erase(v1.begin());
printVector(v1);

//清空
//v1.erase(v1.begin(),v1.end());
//printVector(v1);

v1.clear();
printVector(v1);


}

int main() {
test();
return 0;
}

/*
运行结果:

10 20 30 40 50
10 20 30 40
100 10 20 30 40
1000 1000 100 10 20 30 40
1000 100 10 20 30 40
*/

vector数据的存取

函数原型:

  • at(int idx); 返回索引idx所指的数据
  • operator[]; 返回索引idx所指的数据
  • front(); 返回容器中第一个数据元素
  • back(); 返回容器中最后一个数据元素

代码块:

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
#include <iostream>
#include <vector>
using namespace std;


void test()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}

cout << "用[]方式访问元素:" << endl;
for (int i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;

cout << "用at方式访问元素:" << endl;
for (int i = 0; i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;

cout << "第一个元素为" << v1.front() << endl;
cout << "最后一个元素为" << v1.back() << endl;
}

int main() {
test();
return 0;
}

/*
运行结果

用[]方式访问元素:
0 1 2 3 4 5 6 7 8 9
用at方式访问元素:
0 1 2 3 4 5 6 7 8 9
第一个元素为0
最后一个元素为9
*/

vector互换容器

函数原型:

  • swap(vec); 将vec与本身的元素互换

代码块:

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
#include <iostream>
#include <vector>
using namespace std;

void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}


vector<int>v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}

cout << "互换前" << endl;
printVector(v1);
printVector(v2);

v1.swap(v2);

cout << "互换后" << endl;
printVector(v1);
printVector(v2);
}

//实际应用 ---> 收缩内存
void test02()
{
vector<int>v;
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
}

cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;

v.resize(10); //重新指定大小
cout << "v的容量为:" << v.capacity() << endl; //容量浪费
cout << "v的大小为:" << v.size() << endl;

//巧用swap收缩内存
vector<int>(v).swap(v);
//vector<int>(v) 匿名对象用v做初始化
//匿名对象.swap(v)
//再将匿名对象与v交换
//匿名对象的特点,当前行若为匿名对象,下一行将自动回收匿名对象内存
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}

int main() {
//test();
test02();
return 0;
}

/*
运行结果

v的容量为:138255
v的大小为:100000
v的容量为:138255
v的大小为:10
v的容量为:10
v的大小为:10
*/

vector预留空间

功能描述:

  • 减少了vector在动态扩展容量时的扩展次数

函数原型:

  • reserve(int len); 容器预留len个元素长度,预留位置不初始化,元素不可访问

代码块:

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
#include <iostream>
#include <vector>
using namespace std;

void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
vector<int>v;

int num = 0;
int* p = NULL;

//不预留空间
cout << "不预留空间:";
for (int i = 0; i < 100000; i++)
{
v.push_back(i);
if (p != &v[0])
{
num++;
p = &v[0];
}
}

cout << "共开辟了"<< num << "次" << endl;

//利用reserve预留空间
vector<int>v1;
v1.reserve(100000);

num = 0;
int* p1 = NULL;
cout << "预留空间:";
for (int i = 0; i < 100000; i++)
{
v1.push_back(i);
if (p1 != &v1[0])
{
num++;
p1 = &v1[0];
}
}

cout << "共开辟了" << num << "次" << endl;

}

int main() {
test();
return 0;
}

/*
不预留空间:共开辟了30次
预留空间:共开辟了1次
*/

0x03.deque

deque基本概念

功能:

  • 双端数组,可以对双端进行插入删除造作

deque与vector区别:

  • vector对头部的插入删除效率低,数据量越大,效率越低
  • deque相对而言,对头部的插入删除速度会比vector快
  • vector访问元素时的速度会比deque快,这与两者内部实现有关

deque内部工作原理:

deque内部有一个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据

中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

deque容器的迭代器也是支持随机访问的

deque构造函数

函数原型:

  • deque<T>deqT; 默认构造函数
  • deque(beg,end); 构造函数将[ beg , end )区间中的元素拷贝给本身
  • deque(n,elem); 构造函数将n个elem拷贝给本身
  • deque(const deque& deq) 拷贝构造函数

代码块:

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
#include <iostream>
#include <deque>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d;
for (int i = 0; i < 10; i++)
{
d.push_back(i);
}
printDeque(d);

deque<int>d2(d.begin(),d.end());
printDeque(d2);

deque<int>d3(10, 100);
printDeque(d3);

deque<int>d4(d3);
printDeque(d4);

}

int main() {
test();
return 0;
}

/*
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
100 100 100 100 100 100 100 100 100 100
100 100 100 100 100 100 100 100 100 100
*/

deque赋值操作

  • deque& operator=(const deque& deq);
  • assign(beg,end);
  • assign(n,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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <deque>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);

deque<int>d2;
d2 = d1;
printDeque(d2);

deque<int>d3;
d3.assign(d2.begin(), d2.end());
printDeque(d3);

deque<int>d4;
d4.assign(10, 100);
printDeque(d4);
}

int main() {
test();
return 0;
}
/*
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
100 100 100 100 100 100 100 100 100 100
*/

deque大小操作

  • deque.empty();
  • deque.size();
  • deque.resize(num);
  • deque.resize(num,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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <deque>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);

if (d1.empty())
{
cout << "Kong" << endl;
}
else
{
cout << "d1不为空" << endl;
cout << "d1的大小为:" << d1.size() << endl;
//deque容器没有容量的概念
}

//重新指定大小
//d1.resize(15);
d1.resize(15, 3);
printDeque(d1);

d1.resize(5);
printDeque(d1);
}

int main() {
test();
return 0;
}

小结:

  • deque没有容量的概念
  • 判断是否为空 — empty
  • 返回元素个数 — size
  • 重新指定个数 — resize

deque插入与删除

函数原型:

两端的插入操作:

  • push_back(elem);
  • push_front(elem);
  • pop_back(elem);
  • pop_front(elem);

指定位置操作:

  • insert(pos,elem); 在pos位置插入一个elem元素的拷贝,返回新数据的位置
  • insert(pos,n,elem); 在pos位置插入n个elem元素,无返回值
  • insert(pos,beg,end); 在pos位置上插入[ beg , end )区间的数据,无返回值
  • clear(); 清空容器
  • erase(beg,end); 删除[ beg , end )区间的数据,返回下一个数据的位置
  • erase(pos); 删除pos位置的数据,返回下一个数据的位置

代码块:

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
#include <iostream>
#include <deque>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d1;

//尾插
d1.push_back(10);
d1.push_back(20);

//头插
d1.push_front(30);
d1.push_front(40);

printDeque(d1);

//尾删
d1.pop_back();
printDeque(d1);
//头删
d1.pop_front();
printDeque(d1);

}

void test02()
{
deque<int>d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);

printDeque(d1);

//insert插入
d1.insert(d1.begin(), 1000);
printDeque(d1);

d1.insert(d1.begin(), 2, 8888);
printDeque(d1);


deque<int>d2;
d2.push_back(1);
d2.push_back(2);
d2.push_back(3);


d1.insert(d1.begin(), d2.begin(), d2.end());
printDeque(d1);


}
void test03()
{
deque<int>d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
printDeque(d1);

//删除
deque<int>::iterator it = d1.begin();
it++;
d1.erase(it);
printDeque(d1);

//清空1
//d1.erase(d1.begin(), d1.end());

//清空2
d1.clear();
}


int main() {
cout << "test测试:" << endl;
test();
cout << "test02测试:" << endl;
test02();
cout << "test03测试(删除):" << endl;
test03();
return 0;
}

/*
test测试:
40 30 10 20
40 30 10
30 10
test02测试:
200 100 10 20
1000 200 100 10 20
8888 8888 1000 200 100 10 20
1 2 3 8888 8888 1000 200 100 10 20
test03测试(删除):
200 100 10 20
200 10 20
*/

注意:插入删除的参数为迭代器

deque数据存取

函数原型:

  • at(int index);
  • operator[];
  • front();
  • end();

代码块:

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
#include <iostream>
#include <deque>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
d.push_front(300);


for (int i = 0; i < d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl;

for (int i = 0; i < d.size(); i++)
{
cout << d.at(i) << " ";
}
cout << endl;

cout <<"front = " << d.front() << endl;

cout << "back = " << d.back() << endl;
}

int main() {
test();
return 0;
}

/*
300 200 100 10 20 30
300 200 100 10 20 30
front = 300
back = 30
*/

deque排序

功能描述:

  • 利用算法时间对deque容器进行排序

算法:

  • sort(iterator beg,iterator end) 对beg,end区间内元素进行排序

代码块:

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
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void test()
{
deque<int>d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(1000);
d.push_front(222);
d.push_front(123);

cout << "before sort:";
printDeque(d);

//排序 默认排序规则 从小到大 升序
//对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其进行排序
//vector容器也可以利用sort进行排序
cout << "after sort:";
sort(d.begin(), d.end());
printDeque(d);

}

int main() {
test();
return 0;
}

/*
before sort:123 222 1000 10 20 30
after sort:10 20 30 123 222 1000
*/

0x04.案例-评委打分

案例描述

有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除最低分,给出平均分

实现步骤

1、创建五名选手,放在vector中
2、遍历vector容器,去除来每一个选手,执行for循环,可以吧10个评分打分存在deque容器中
3、用sort对deque排序,去除最高分与最低分
4、deque容器遍历一遍,累加总分
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
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
#include <iostream>
#include <string>
#include <deque>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;

class Person
{
public:
Person(string name, int score)
{
this->m_Name = name;
this->m_Score = score;
}

string m_Name;
int m_Score;
};

void printDeque(const deque<int>& d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << (*it) << " ";
}
cout << endl;
}

void createPerson(vector<Person>& v)
{
string nameSeed = "ABCDE";
for (int i = 0; i < 5; i++)
{
string name = "选手";
name += nameSeed[i];

int score = 0;

Person p(name, score);

//将创建的Person对象放入容器中
v.push_back(p);
}
}

void setScore(vector<Person>& v)
{

for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
//将评委的分放入deque中
deque<int>d;
for (int i = 0; i < 10; i++)
{
int score = rand() % 41 + 60;
d.push_back(score);
}

//排序
sort(d.begin(), d.end());

//cout << "\t" << (*it).m_Name << "记录" << endl;
//cout << "打分详情:" << endl;
//printDeque(d);


//去除最值分
d.pop_back();
d.pop_front();

//计算总分
int sum = 0;
for (deque<int>::iterator vit = d.begin(); vit != d.end(); vit++)
{
sum += (*vit);
}

int avg = sum / d.size();
it->m_Score = avg;

//cout << "去除最值的打分详情:" << endl;
//printDeque(d);
//cout << "总分为: " << sum << " 平均分为:" << (sum / d.size()) << endl;
//cout << "\n\n" << endl;
}

}

void showScore(vector<Person>&v)
{
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名: " << (*it).m_Name << " 平均分: " << (*it).m_Score << endl;
}
}

void test()
{
srand((unsigned int)time(NULL));

//1、创建5名选手
vector<Person>v;
createPerson(v);
////测试
//for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
//{
// cout << "姓名: " << (*it).m_Name << " 分数: " << (*it).m_Score << endl;
//}
//2、给5个人打分
setScore(v);

//3、打印平均分
showScore(v);
}

int main() {
test();
return 0;
}

0x05.后记

在之后的学习中我们将接着学习stack queuelistset/multisetmap/multimap等等容器。



人在旅途,难免会遇到荆棘和坎坷,但风雨过后,一定会有美丽的彩虹。