Cpp_note_2

Cpp_note_2

Charles Lv7

C++笔记汇总2 模板及STL

1.模板

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
template <typename T>
void My_swap(T& a, T& b) {
T tmp = a;
a = b;
b = tmp;
}
void test01() {
int a, b;
a = 10, b = 20;
// 1.自动类型推导
My_swap(a, b);
// 2.显示指定类型
My_swap<int>(a, b);
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}
//函数模板注意事项:
template <class T> // typename可以替换为class
void MySwap(T& a, T& b) {
T tmp = a;
a = b;
b = tmp;
}
// 1.自动类型推导必须推导出一致的数据类型T才能使用
void test02() {
int a, b;
a = 10, b = 20;
char c = 'c';
MySwap(a, b);
// MySwap(a, c);//类型不一致,报错
cout << "a:" << a << endl;
cout << "b:" << b << endl;
}
// 2.模板必须要确定出T的数据类型,才可以使用
template <class T>
void func() {
cout << "func()" << endl;
}
void test03() {
// func();//报错,推导不出T的类型
func<int>();
}

普通函数和函数模板区别:

1.普通模板调用可以发生隐式类型转换

2.函数模板用自动类型推导,不可以发生隐式类型转换

3.函数模板用显示指定类型,可以发生隐式类型转换

普通函数和函数模板调用的规则:

1.如果函数模板和普通函数都可以调用,优先调用普通函数

2.可以通过空模板参数列表强制调用函数模板

3.函数模板可以发生函数重载

4.如果函数模板可以产生更好的匹配,优先调用函数模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void myPrint(int a, int b) {
cout << "common" << endl;
}
template <class T>
void myPrint(T a, T b) {
cout << "template-2" << endl;
}
template <class T>
void myPrint(T a, T b, T c) {
cout << "template-3" << endl;
}
void test04() {
int a = 10;
int b = 20;
myPrint(a, b);
// 空模板参数列表
myPrint<>(a, b);
double c = 10;
double d = 20;
myPrint(c, d);
}

模板的局限性

模板并不是万能的,有些特定数据类型,需要用具体化方式做特殊实现

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
class Person {
public:
int age;
string name;
};
template <class T>
bool myCompare(T& a, T& b) {
if (a == b) {
return false;
} else {
return true;
}
}
template <>
bool myCompare(Person& a, Person& b) {
if (a.age == b.age && a.name == b.name) {
return true;
} else {
return false;
}
}
void test05() {
int a = 10;
int b = 20;
cout << myCompare(a, b) << endl;
// 如果用一个类就会报错,所以要重新定义
Person p1, p2;
p1.age = 10;
p2.age = 10;
p1.name = "小红";
p2.name = "小红";
cout << myCompare(p1, p2) << endl;
}

类模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <class NameType, class AgeType = int>  // 默认参数
class Person1 {
public:
Person1(NameType name, AgeType age) {
this->name = name;
this->age = age;
}
NameType name;
AgeType age;
void showPerson() {
cout << "age:" << this->age << endl;
cout << "name:" << this->name << endl;
}
};
void test06() {
Person1<string, int> p1("杜金阳", 18);
p1.showPerson();
}

类模板和函数模板的区别:

1.类模板没有自动类型推导的使用方法

2.类模板在模板参数列表中可以有默认参数

类模板和普通模板在成员函数创造时机的区别:

1.普通类中成员函数一开始就可以创建

2.类模板中的成员函数在调用时才创建

类模板对象做函数参数

三种传入方式

1.指定传入的类型[常用]

2.参数模板化

3.整个类模板化

类模板遇到继承时的注意事项:

1.当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型

2.如果不指定,编译器无法给子类分配内存

3.如果想灵活指定出父类中T的类型,子类也需变为类模板

类模板和友元:

全局函数类内实现-直接在类内声明友元即可

全局函数类外实现-需要提前让编译器知道全局函数的存在

2.STL

algorithm 部分

常用算术生成算法accumulate:计算区间内容器元素累计总和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v;
for (int i = 0; i <= 100; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), myPrint());
puts("");
int ans = accumulate(v.begin(), v.end(), 0);
//参数3为起始累加值
printf("%d", ans);
}

常见查找算法adjacent_find:查找相邻重复元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void test() {
vector<int> v;
v.push_back(20);
v.push_back(50);
v.push_back(10);
v.push_back(10);
v.push_back(30);
v.push_back(40);
v.push_back(20);
vector<int>::iterator pos = adjacent_find(v.begin(), v.end());
if (pos == v.end()) {
printf("not discover\n");
} else {
printf("val:%d\n", *pos);
}
}
1
2
3
4
5
6
7
8
9
10
11
void test() {
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
bool ret = binary_search(v.begin(), v.end(), 30);
//查找必须为有序序列
printf("val:%d\n", ret);
}

常用拷贝和替换算法copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i * 10);
}
vector<int> v2;
v2.resize(v1.size());
copy(v1.begin(), v1.end(), v2.begin());
for_each(v2.begin(), v2.end(), myPrint());
puts("");
}

常用查找算法count

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
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(50);
v.push_back(60);
v.push_back(20);
v.push_back(20);
v.push_back(40);
v.push_back(50);
int num = count(v.begin(), v.end(), 20);
printf("%d", num);
}
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
bool operator==(const Person& p) {
if (this->age == p.age) {
return true;
} else {
return false;
}
}
};
void test02() {
vector<Person> v;
Person p1("Charles", 19);
Person p2("Lucas", 23);
Person p3("Jerry", 19);
Person p4("Tom", 14);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
Person p("Luis", 14);
int num = count(v.begin(), v.end(), p);
printf("%d", num);
}

常用查找算法count_if

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
class cmp {
public:
bool operator()(int val) { return val > 20; }
};
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(50);
v.push_back(60);
v.push_back(20);
v.push_back(20);
v.push_back(40);
v.push_back(50);
int num = count_if(v.begin(), v.end(), cmp());
printf("%d ", num);
}
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
bool operator==(const Person& p) {
if (this->age == p.age) {
return true;
} else {
return false;
}
}
};
class cmp2 {
public:
bool operator()(const Person& p) { return p.age > 15; }
};
void test02() {
vector<Person> v;
Person p1("Charles", 19);
Person p2("Lucas", 23);
Person p3("Jerry", 19);
Person p4("Tom", 14);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
int num = count_if(v.begin(), v.end(), cmp2());
printf("%d ", num);
}

常用算术生成算法fill:向容器中填充指定的元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v;
for (int i = 0; i <= 100; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), myPrint());
puts("");
fill(v.begin(), v.begin() + 8, 0);
//参数3为起始累加值
for_each(v.begin(), v.end(), myPrint());
puts("");
}

常见查找算法find

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
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int>::iterator it = find(v.begin(), v.end(), 5);
if (it == v.end()) {
printf("not discover\n");
} else {
printf("val:%d\n", *it);
}
}
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
bool operator==(const Person& p) {
if (this->age == p.age && this->name == p.name) {
return true;
} else {
return false;
}
}
//自定义类型需要重载以确定如何对比数据类型
};
void test02() {
vector<Person> v;
Person p1("Charles", 19);
Person p2("Lucas", 23);
Person p3("Jerry", 19);
Person p4("Tom", 14);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
vector<Person>::iterator it = find(v.begin(), v.end(), p2);
if (it == v.end()) {
printf("not discover\n");
} else {
printf("key:%s val:%d\n", it->name.c_str(), it->age);
}
}

常见查找算法find_if

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
class cmp {
public:
bool operator()(int val) { return val > 5; }
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int>::iterator pos = find_if(v.begin(), v.end(), cmp());
if (pos == v.end()) {
printf("not discover\n");
} else {
printf("val:%d\n", *pos);
}
}
class Person {
public:
string Name;
int Age;

public:
Person(string name, int age) {
this->Name = name;
this->Age = age;
}
bool operator==(const Person& p) {
if (this->Age == p.Age && this->Name == p.Name) {
return true;
} else {
return false;
}
}
};
class my_cmp {
public:
bool operator()(Person& p) { return p.Age > 20; }
};
void test02() {
vector<Person> v;
Person p1("Charles", 19);
Person p2("Lucas", 23);
Person p3("Jerry", 19);
Person p4("Tom", 14);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
vector<Person>::iterator it = find_if(v.begin(), v.end(), my_cmp());
if (it == v.end()) {
printf("not discover\n");
} else {
printf("key:%s val:%d\n", it->Name.c_str(), it->Age);
}
}

常用遍历算法for_each

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 普通函数
void print01(int val) {
printf("%d ", val);
}
// 仿函数
class print02 {
public:
void operator()(int val) { printf("%d", val); }
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
for_each(v.begin(), v.end(), print01);
puts("");
for_each(v.begin(), v.end(), print02());
puts("");
}

常用排序算法merge

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
// merge用于将两个有序序列合并
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void test01() {
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int> v2;
v2.push_back(15);
v2.push_back(25);
v2.push_back(35);
v2.push_back(45);
v2.push_back(55);
// 升序
vector<int> v;
v.resize(v1.size() + v2.size()); //分配空间
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
printVector(v);
}

常用排序算法random_shuffle:洗牌 指定范围内随机调整次序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void test() {
srand((unsigned int)time(NULL));
//时间随机数种子,用于利用时间生成真正的随机数
vector<int> v;
for (int i = 1; i <= 10; i++) {
v.push_back(i * 10);
}
printVector(v);
random_shuffle(v.begin(), v.end());
printVector(v);
}

常用拷贝和替换算法replace

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(50);
v.push_back(60);
v.push_back(20);
v.push_back(20);
v.push_back(40);
v.push_back(50);
for_each(v.begin(), v.end(), myPrint());
puts("");
replace(v.begin(), v.end(), 20, 200);
for_each(v.begin(), v.end(), myPrint());
puts("");
}

常用拷贝和替换算法replace_if

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
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
class cmp {
public:
bool operator()(int val) { return val > 20; }
};
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(50);
v.push_back(60);
v.push_back(20);
v.push_back(20);
v.push_back(40);
v.push_back(50);
for_each(v.begin(), v.end(), myPrint());
puts("");
replace_if(v.begin(), v.end(), cmp(), 200);
for_each(v.begin(), v.end(), myPrint());
puts("");
}

常见排序算法reverse: 反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void test() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(50);
v.push_back(60);
v.push_back(20);
sort(v.begin(), v.end());
printVector(v);
reverse(v.begin(), v.end());
printVector(v);
}

常用集合算法set_difference:求两个容器的差集

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
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v1;
for (int i = 0; i <= 50; i++) {
v1.push_back(i * 2);
}
vector<int> v2;
for (int i = 0; i <= 20; i++) {
v2.push_back(i * 5);
}
vector<int> v1_v2; // v1-v2
v1_v2.resize(v1.size());
vector<int>::iterator it_end1 = set_difference(
v1.begin(), v1.end(), v2.begin(), v2.end(), v1_v2.begin());
vector<int> v2_v1; // v2-v1
v2_v1.resize(v2.size());
vector<int>::iterator it_end2 = set_difference(
v2.begin(), v2.end(), v1.begin(), v1.end(), v2_v1.begin());
for_each(v1.begin(), v1.end(), myPrint());
puts("");
for_each(v2.begin(), v2.end(), myPrint());
puts("");
for_each(v1_v2.begin(), it_end1, myPrint());
puts("");
for_each(v2_v1.begin(), it_end2, myPrint());
puts("");
}

常用集合算法set_union:求两个容器的并集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v1;
for (int i = 0; i <= 50; i++) {
v1.push_back(i * 2);
}
vector<int> v2;
for (int i = 0; i <= 20; i++) {
v2.push_back(i * 5);
}
vector<int> v;
v.resize(v2.size() + v1.size());
vector<int>::iterator it_end =
set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin());
for_each(v1.begin(), v1.end(), myPrint());
puts("");
for_each(v2.begin(), v2.end(), myPrint());
puts("");
for_each(v.begin(), it_end, myPrint());
puts("");
}

常用排序算法sort

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
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void test01() {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(40);
v.push_back(50);
v.push_back(60);
v.push_back(20);
v.push_back(20);
v.push_back(40);
v.push_back(50);
// 升序
sort(v.begin(), v.end());
printVector(v);
// 降序
sort(v.begin(), v.end(), greater<int>());
printVector(v);
}

常用拷贝和替换算法swap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class myPrint {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i + 1);
}
vector<int> v2;
for (int i = 0; i < 10; i++) {
v2.push_back(i * 10);
}
v1.swap(v2);
//或swap(v1,v2)
for_each(v1.begin(), v1.end(), myPrint());
puts("");
for_each(v2.begin(), v2.end(), myPrint());
puts("");
}

常用遍历算法transform

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Transform {
public:
int operator()(int v) { return v + 10; }
};
class print02 {
public:
void operator()(int val) { printf("%d ", val); }
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
vector<int> vTarget;
vTarget.resize(v.size()); //开辟空间
transform(v.begin(), v.end(), vTarget.begin(), Transform());
for_each(vTarget.begin(), vTarget.end(), print02());
puts("");
}

Container 部分

deque

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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
void printDeque(const deque<int>& d) {
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void build_deque() {
//构造容器的4种方式
deque<int> d1;
for (int i = 0; i < 10; i++) {
d1.push_back(i);
d1.push_front(i);
} // deque可以从首尾两个方向插入
printDeque(d1);
deque<int> d2(d1.begin(), d1.end());
printDeque(d2);
deque<int> d3(10, 100);
printDeque(d3);
deque<int> d4(d3);
printDeque(d4);
}
void value_deque() {
deque<int> d1;
for (int i = 0; i < 10; i++) {
d1.push_back(i);
}
printDeque(d1);
// operator = 赋值
deque<int> d2;
d2 = d1;
printDeque(d2);
// assign 赋值
deque<int> d3;
d3.assign(d1.begin(), d1.end());
printDeque(d3);
deque<int> d4;
d4.assign(10, 100);
printDeque(d4);
}
void size_deque() {
deque<int> d1;
for (int i = 0; i < 10; i++) {
d1.push_back(i);
}
if (d1.empty()) {
printf("d1为空\n");
} else {
printf("d1不为空\n");
printf("大小:%d\n", d1.size());
// deque容器没有容量概念
}
// 重新指定大小
d1.resize(15);
printDeque(d1); //默认0填充
d1.resize(17, 100);
printDeque(d1);
d1.resize(5); //小于容量会将多余部分删除
printDeque(d1);
}
void calc_deque() {
deque<int> d1;
d1.push_back(10); //尾插法
d1.push_front(40); //头插法
d1.push_back(20);
d1.push_front(50);
d1.push_back(30);
printDeque(d1);
d1.pop_back(); //尾部删除
d1.pop_front();
d1.insert(d1.begin(), 100);
d1.insert(d1.begin(), 2, 1000);
d1.insert(d1.begin(), d1.begin() + 3, d1.end());
//在某个位置插入某两个区间之间的所有值
printDeque(d1);
d1.erase(d1.begin());
d1.erase(d1.begin() + 3, d1.end());
printDeque(d1);
d1.clear();
}
void operator_deque() {
deque<int> d1;
for (int i = 0; i < 5; i++) {
d1.push_back(i);
d1.push_front(i);
}
//利用[]访问元素
for (int i = 0; i < d1.size(); i++) {
printf("%d ", d1[i]);
}
puts("");
// 利用at访问
for (int i = 0; i < d1.size(); i++) {
printf("%d ", d1.at(i));
}
puts("");
printf("%d %d", d1.front(), d1.back());
}
void sort_deque() {
deque<int> d;
d.push_back(20);
d.push_back(30);
d.push_back(40);
d.push_front(50);
d.push_front(60);
d.push_front(70);
printDeque(d);
sort(d.begin(), d.end()); //默认升序
//对于支持随机访问的迭代器的容器,都支持利用sort算法排序(利用vector也支持sort)
printDeque(d);
}
int main() {
build_deque();
value_deque();
size_deque();
calc_deque();
operator_deque();
sort_deque();
return 0;
}

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
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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
//链表list容器[双向循环链表]
void printList(const list<int>& l) {
for (list<int>::const_iterator it = l.begin(); it != l.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void build_list() {
list<int> l1;
l1.push_back(40);
l1.push_front(10);
l1.push_back(20);
l1.push_front(30);
l1.push_back(50);
printList(l1);
list<int> l2(l1.begin(), l1.end());
printList(l2);
list<int> l3(l1);
printList(l3);
list<int> l4(10, 100);
printList(l4);
}
void value_list() {
//赋值
list<int> l1;
l1.push_back(10);
l1.push_back(20);
l1.push_back(30);
l1.push_back(40);
l1.push_back(50);
printList(l1);
list<int> l2 = l1;
printList(l2);
list<int> l3;
l3.assign(l2.begin(), l2.end());
printList(l3);
list<int> l4;
l4.assign(10, 100);
printList(l4);
// 交换
list<int> l5;
l5.assign(10, 100);
l1.swap(l5);
printList(l1);
printList(l5);
}
void size_list() {
list<int> l1;
for (int i = 0; i < 10; i++) {
l1.push_back(i);
}
if (l1.empty()) {
printf("l1为空\n");
} else {
printf("l1不为空\n");
printf("大小:%d\n", l1.size());
// list容器没有容量概念
}
// 重新指定大小
l1.resize(15);
printList(l1); //默认0填充
l1.resize(17, 100);
printList(l1);
l1.resize(5); //小于容量会将多余部分删除
printList(l1);
}
void calc_list() {
list<int> l1;
l1.push_back(10); //尾插法
l1.push_front(40); //头插法
l1.push_back(20);
l1.push_front(50);
l1.push_back(30);
printList(l1);
l1.pop_back(); //尾部删除
l1.pop_front();
l1.insert(l1.begin(), 100);
l1.insert(l1.begin(), 2, 1000);
l1.insert(l1.begin(), l1.begin(), l1.end());
//在某个位置插入某两个区间之间的所有值
printList(l1);
l1.remove(10); //删除容器中所有与elem值匹配的元素
list<int>::iterator it = l1.begin();
l1.erase(it++);
l1.erase(++it, l1.end());
printList(l1);
l1.clear();
}
void operator_list() {
list<int> l1;
for (int i = 0; i < 5; i++) {
l1.push_back(i);
l1.push_front(i);
}
printf("%d %d", l1.front(), l1.back());
}
// list不能使用[]或at方法进行访问
bool cmp(int v1, int v2) {
return v1 > v2;
}
void function_list() {
list<int> l1;
l1.push_back(10);
l1.push_back(50);
l1.push_back(30);
l1.push_back(20);
l1.push_back(40);
printList(l1);
//反转
l1.reverse();
printList(l1);
// 排序
l1.sort();
//这里不是随机访问的迭代器,所以不能使用迭代器索引排序
printList(l1);
l1.sort(cmp);
printList(l1);
}
int main() {
build_list();
value_list();
size_list();
calc_list();
operator_list();
function_list();

return 0;
}

map

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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// map中所有元素都是pair,第一个为key,第二个为value
// map底层为二叉树
// 所有元素会按照key自动排序
/* map和multimap的区别:
1.map不允许出现重复key元素,value可以重复
2.multimap允许出现重复key元素 */
void printMap(map<int, int>& m) {
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
printf("key:%d value:%d\n", it->first, it->second);
}
puts("");
}
void build_map() {
map<int, int> m1;
m1.insert(pair<int, int>(1, 21373191));
m1.insert(pair<int, int>(3, 21373119));
m1.insert(pair<int, int>(2, 21373181));
m1.insert(pair<int, int>(4, 21373190));
m1.insert(pair<int, int>(3, 21373190));
// key相同时直接插入失败,而Java中为覆盖
printMap(m1); //自动排序,可以存在重复value值
map<int, int> m2(m1);
printMap(m2);
map<int, int> m3;
m3 = m1;
printMap(m3);
}
void size_map() {
map<int, int> m1;
//大小
m1.insert(pair<int, int>(1, 21373191));
m1.insert(pair<int, int>(3, 21373119));
m1.insert(pair<int, int>(2, 21373181));
m1.insert(pair<int, int>(4, 21373190));
printMap(m1);
if (m1.empty()) {
printf("m1为空\n");
} else {
printf("m1不为空\n");
printf("大小:%d\n", m1.size());
}
// 交换
map<int, int> m2;
m2.insert(pair<int, int>(4, 191));
m2.insert(pair<int, int>(3, 119));
m2.insert(pair<int, int>(5, 181));
m2.insert(pair<int, int>(6, 190));
m1.swap(m2);
printMap(m1);
printMap(m2);
}
void calc_map() {
map<int, int> m1;
//四种插入方式
m1.insert(pair<int, int>(1, 21373191));
m1.insert(make_pair(3, 21373119));
m1.insert(map<int, int>::value_type(2, 21373181));
m1[4] = 21373190; //不建议用这种方式创建,但适合用来访问value
printMap(m1);

m1.erase(m1.begin());
map<int, int>::iterator it = m1.begin();
it++;
m1.erase(++it, m1.end());
m1.erase(2); //类似remove,按照key删除
printMap(m1);
m1.clear();
}
void statistics_map() {
map<int, int> m;
m.insert(pair<int, int>(1, 21373191));
m.insert(pair<int, int>(3, 21373119));
m.insert(pair<int, int>(2, 21373181));
m.insert(pair<int, int>(4, 21373190));
//查找
map<int, int>::iterator pos = m.find(3);
if (pos != m.end()) {
printf("key:%d value:%d\n", pos->first, pos->second);
} else {
printf("not discover\n");
}
// 统计
int num = m.count(2);
printf("%d\n", num);
}
class cmp {
public:
bool operator()(int v1, int v2) { return v1 > v2; }
};
void sort_map() {
map<int, int> m1;
m1.insert(pair<int, int>(1, 21373191));
m1.insert(pair<int, int>(3, 21373119));
m1.insert(pair<int, int>(2, 21373181));
m1.insert(pair<int, int>(4, 21373190));
for (map<int, int>::iterator it = m1.begin(); it != m1.end(); it++) {
printf("key:%d value:%d\n", it->first, it->second);
}
puts("");
//降序排列
map<int, int, cmp> m2;
m2.insert(pair<int, int>(1, 21373191));
m2.insert(pair<int, int>(3, 21373119));
m2.insert(pair<int, int>(2, 21373181));
m2.insert(pair<int, int>(4, 21373190));
for (map<int, int, cmp>::iterator it = m2.begin(); it != m2.end(); it++) {
printf("key:%d value:%d\n", it->first, it->second);
}
puts("");
}
int main() {
// build_map();
// size_map();
// calc_map();
statistics_map();
// sort_map();
return 0;
}
map与unordered_map的区别

对于map的底层原理,是通过红黑树(一种非严格意义上的平衡二叉树)来实现的,因此map内部所有的数据都是有序的(默认按key进行升序排序),map的查询、插入、删除操作的时间复杂度都是O(logn)。
unordered_map和map类似,都是存储的key-value的值,可以通过key快速索引到value。不同的是unordered_map不会根据key的大小进行排序,存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的。unordered_map的底层是一个防冗余的哈希表(开链法避免地址冲突)。

queue

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 <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// queue容器
void build_queue() {
queue<int> q;
q.push(10);
q.push(50);
q.push(40);
q.push(30);
q.push(20);
printf("%d\n", q.size());
printf("%d\n", q.back());
while (!q.empty()) {
printf("%d ", q.front());
q.pop();
}
}
int main() {
build_queue();
return 0;
}

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
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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// set为集合,底层结构为二叉树
// 所有元素都会在插入时自动被排序
/* set和multiset的区别:
1.set不允许出现重复元素
2.multiset允许出现重复元素 */
void printSet(set<int>& s) {
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void printMultiset(multiset<int>& ms) {
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
printf("%d ", *it);
}
puts("");
}
void build_set() {
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(30);
s1.insert(40);
printSet(s1); //自动排序且去除重复元素
set<int> s2(s1);
printSet(s2);
set<int> s3;
s3 = s2;
printSet(s3);
}
void size_set() {
set<int> s1;
//大小
for (int i = 0; i < 10; i++) {
s1.insert(i);
}
printSet(s1);
if (s1.empty()) {
printf("s1为空\n");
} else {
printf("s1不为空\n");
printf("大小:%d\n", s1.size());
}
// 交换
set<int> s2;
for (int i = 0; i < 10; i++) {
s2.insert(i * 10);
}
s1.swap(s2);
printSet(s1);
printSet(s2);
}
void calc_set() {
set<int> s1;
for (int i = 0; i < 10; i++) {
s1.insert(i * 10);
}
s1.insert(100);
printSet(s1);
s1.erase(s1.begin());
set<int>::iterator it = s1.begin();
it++;
it++;
s1.erase(++it, s1.end());
s1.erase(100); //类似remove,特有重载
printSet(s1);
s1.clear();
}
void statistics_set() {
set<int> s;
s.insert(10);
s.insert(40);
s.insert(30);
s.insert(20);
//查找
set<int>::iterator pos = s.find(30);
if (pos != s.end()) {
printf("%d\n", *pos);
} else {
printf("not discover\n");
}
// 统计
int num = s.count(20);
printf("%d\n", num);
}
void differ_multiset() {
set<int> s;
s.insert(10);
s.insert(10);
multiset<int> ms;
ms.insert(10);
ms.insert(10);
printSet(s);
printMultiset(ms);
}
void pair_set() {
// pair对组创建
pair<string, int> p1("Charles", 19);
printf("%s %d\n", p1.first.c_str(), p1.second);
// printf不能直接输出String字符串类型,需要如上转化,而cout可以
pair<string, int> p2 = make_pair("Jerry", 23);
printf("%s %d\n", p2.first.c_str(), p2.second);
}
class cmp {
public:
bool operator()(int v1, int v2) { return v1 > v2; }
};
class Person {
public:
Person(string name, int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class cmp_Class {
public:
bool operator()(const Person& p1, const Person& p2) {
if (p1.m_age != p2.m_age) {
return p1.m_age > p2.m_age;
} else {
return strcmp(p1.m_name.c_str(), p2.m_name.c_str());
}
}
};
void sort_set() {
set<int> s1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
s1.insert(50);
printSet(s1);
//降序排列
set<int, cmp> s2;
s2.insert(10);
s2.insert(20);
s2.insert(30);
s2.insert(40);
s2.insert(50);
for (set<int, cmp>::iterator it = s2.begin(); it != s2.end(); it++) {
//需要修改迭代器
printf("%d ", *it);
}
puts("");
// set存放自定义类型
set<Person, cmp_Class> s;
Person p1("Charles", 19);
Person p2("Lucas", 25);
Person p3("Tom", 19);
Person p4("Jerry", 28);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person, cmp_Class>::iterator it = s.begin(); it != s.end(); it++) {
printf("%s %d\n", it->m_name.c_str(), it->m_age);
}
}
int main() {
build_set();
size_set();
calc_set();
statistics_set();
differ_multiset();
pair_set();
sort_set();
return 0;
}

stack

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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// stack容器
void build_stack() {
stack<int> s;
s.push(10); //入栈
s.push(20);
s.push(30);
s.push(40);
if (!s.empty()) { //判断栈是否为空
int temp = s.top();
printf("%d\n", temp);
}
s.pop(); //出栈
cout << s.size() << endl;
}
int main() {
build_stack();
return 0;
}

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
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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// vector相关笔记
void printVector(vector<int>& v) { //用引用的方式传入
for (vector<int>::iterator it = v.begin(); it != v.end();
it++) { //迭代器遍历
printf("%d ", *it);
}
puts("");
}
void build_vector() {
// 创建vector容器并向里面填入数值
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i); //向vector中推入值
}
printVector(v1);
// vector赋值
//方法1:operator=
vector<int> v2;
v2 = v1;
printVector(v2);
//方法2:assign读入
vector<int> v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
//方法3:assign赋值
vector<int> v4;
v4.assign(10, 100); //赋值10个100
printVector(v4);
}
void capacity_vector() {
// vector容器的容量和大小操作
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
if (v1.empty()) {
printf("v1为空\n");
} else {
printf("v1不为空\n");
printf("容量:%d 大小:%d\n", v1.capacity(), v1.size());
//容量>=大小
}
// 重新指定大小
v1.resize(15);
printVector(v1); //默认0填充
v1.resize(15, 100);
printVector(v1);
v1.resize(5); //小于容量会将多余部分删除
printVector(v1);
}
void calc_vector() {
vector<int> v1;
v1.push_back(10); //尾插法
v1.push_back(40);
v1.push_back(20);
v1.push_back(50);
v1.push_back(30);
printVector(v1);
v1.pop_back(); //尾部删除
v1.insert(v1.begin(), 100);
v1.insert(v1.begin(), 2, 1000);
printVector(v1);
v1.erase(v1.begin());
v1.erase(v1.begin() + 3, v1.end());
printVector(v1);
v1.clear();
}
void operator_vector() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
//利用[]访问元素
for (int i = 0; i < v1.size(); i++) {
printf("%d ", v1[i]);
}
puts("");
// 利用at访问
for (int i = 0; i < v1.size(); i++) {
printf("%d ", v1.at(i));
}
puts("");
printf("%d %d", v1.front(), v1.back());
}
void swap_vector() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
vector<int> v2;
for (int i = 9; i >= 0; i--) {
v2.push_back(i);
}
v1.swap(v2); //容器互换
printVector(v1);
printVector(v2);
// 实际用途
vector<int> v;
for (int i = 0; i < 100000; i++) {
v.push_back(i);
}
printf("容量:%d 大小:%d\n", v.capacity(), v.size());
v.resize(3);
vector<int>(v).swap(v); //用于收缩容器容量,避免空间浪费
printf("容量:%d 大小:%d\n", v.capacity(), v.size());
}
void reserve_vector() {
vector<int> v;
//利用reserve预留空间
v.reserve(100000);
int num = 0, *p = NULL; // num统计开辟次数
for (int i = 0; i < 100000; i++) {
v.push_back(i);
if (p != &v[0]) {
p = &v[0];
num++;
}
}
printf("%d", num);
}

int main() {
build_vector();
capacity_vector();
calc_vector();
operator_vector();
swap_vector();
reserve_vector();
return 0;
}

object

Inner_function

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
#include <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
// 内建函数对象
// 1.算数仿函数
// negate 一元仿函数 取反仿函数
void test01() {
negate<int> n;
printf("%d\n", n(50));
}
// plus 二元仿函数 加法
void test02() {
plus<int> p;
printf("%d\n", p(10, 20));
}
/* 类似函数
plus 加法
minus 减法
multiplies 乘法
divides 除法
modulus 取模
negate 取反
*/
// 2.关系仿函数
// greater 大于
void test03() {
vector<int> v;
v.push_back(10);
v.push_back(30);
v.push_back(40);
v.push_back(20);
v.push_back(50);
//降序排列
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
printf("%d ", *it);
}
puts("");
}
// 3.逻辑仿函数
// logical_not 逻辑非
void test04() {
vector<bool> v1;
v1.push_back(true);
v1.push_back(false);
v1.push_back(true);
v1.push_back(false);
for (vector<bool>::iterator it = v1.begin(); it != v1.end(); it++) {
cout << *it << " "; //不知道为什么这里bool不能用printf
}
puts("");
vector<bool> v2;
v2.resize(v1.size()); //首先需要扩大容量
transform(v1.begin(), v1.end(), v2.begin(), logical_not<bool>());
for (vector<bool>::iterator it = v2.begin(); it != v2.end(); it++) {
cout << *it << " ";
}
puts("");
}
int main() {
test01();
test02();
test03();
test04();
return 0;
}

function_object

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 <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
//函数对象
// 1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class MyAdd {
public:
int operator()(int v1, int v2) { return v1 + v2; }
};
void test01() {
MyAdd myAdd;
printf("%d\n", myAdd(10, 10));
}
// 2.函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint {
public:
int count; //内部自己的状态
MyPrint() { this->count = 0; }
void operator()(string test) {
printf("%s\n", test.c_str());
this->count++;
}
};
void test02() {
MyPrint MyPrint;
MyPrint("hello world");
printf("%d\n", MyPrint.count);
}
// 3.函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test) {
mp(test);
}
void test03() {
MyPrint myPrint;
doPrint(myPrint, "Hello c++");
}
int main() {
test01();
test02();
test03();
return 0;
}

predicate

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 <bits/stdc++.h>
using namespace std;
#define M 100007
#define N 1007
#define INF 0x3f3f3f3f
#define ll long long
#define db double
//函数对象
// 1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
class MyAdd {
public:
int operator()(int v1, int v2) { return v1 + v2; }
};
void test01() {
MyAdd myAdd;
printf("%d\n", myAdd(10, 10));
}
// 2.函数对象超出普通函数的概念,函数对象可以有自己的状态
class MyPrint {
public:
int count; //内部自己的状态
MyPrint() { this->count = 0; }
void operator()(string test) {
printf("%s\n", test.c_str());
this->count++;
}
};
void test02() {
MyPrint MyPrint;
MyPrint("hello world");
printf("%d\n", MyPrint.count);
}
// 3.函数对象可以作为参数传递
void doPrint(MyPrint& mp, string test) {
mp(test);
}
void test03() {
MyPrint myPrint;
doPrint(myPrint, "Hello c++");
}
int main() {
test01();
test02();
test03();
return 0;
}
  • Title: Cpp_note_2
  • Author: Charles
  • Created at : 2022-12-28 12:32:48
  • Updated at : 2023-02-09 09:44:14
  • Link: https://charles2530.github.io/2022/12/28/cpp-note-2/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments