结构体
结构体并不是STL中的内容,但这里简单介绍一下,讲解容器时会用到。
引入
当我们处理关联性很强的数据是可以使用结构体变量将这些数据统一存储。
语法
struct 结构体名 {
结构体成员列表
};
示例
#include <bits/stdc++.h>
using namespace std;
// 可以将结构体理解为我们自己定义的一个数据类型
struct student { // 定义一个名为student的结构体
// 结构体内定义的变量称为成员变量
int id; // 学生的学号
int ch; // 学生的语文成绩
int ma; // 学生的数学成绩
} stu1; // 在定义结构体的时候顺便定义了一个stu1的变量
student stu2 = { 2, 90, 90 }; // 定义stu2的同时给stu2赋上初始值
// 定义结构体变量时,可以将结构体名看做一个类似int类型的普通的数据类型
int main() {
cin >> stu1.id >> stu1.ch >> stu1.ma;
printf("%d:%d %d\n", stu1.id, stu1.ch, stu1.ma);
printf("%d:%d %d\n", stu2.id, stu2.ch, stu2.ma);
return 0;
}
读入
1 100 100
输出
1: 100 100
2: 90 90
vector
vector 标准库中的容器,可以实现长度可变的数组的功能。
头文件
#include <vector>
创建vector
vector <int> v1; //vector默认为空,潜在的元素为int类型
vector <char> v2;
struct node { int x, y; };
vector <node> v3;
vector < vector<int> > v4;
上图是一些vector初始化的方法,略有了解即可。
添加元素
使用push_back()添加新元素
#include <bits/stdc++.h>
using namespace std;
vector <int> v1; //vector默认为空,潜在的元素为int类型
vector <char> v2;
struct node { int x, y; };
vector <node> v3;
int main() {
node a;
for (int i = 1; i <= 5; ++i) {
v1.push_back(i); //v1末尾添加一个新元素i
a.x = i, a.y = i * i;
v3.push_back(a); //v3末尾添加一个新元素
}
return 0;
}
访问与遍历
vector可以像数组一样访问对应的元素,但是要注意vector的元素个数,如果超出vector现有的个数程序会报错。
#include <bits/stdc++.h>
using namespace std;
vector <int> v1; //vector默认为空,潜在的元素为int类型
vector <char> v2;
struct node { int x, y; };
vector <node> v3;
int main() {
node a;
for (int i = 1; i <= 5; ++i) {
v1.push_back(i); //v1末尾添加一个新元素i
a.x = i, a.y = i * i;
v3.push_back(a); //v3末尾添加一个新元素
}
//可以通过v1.size()知道v1中的元素个数
printf("v1.size() = %d\n", v1.size());
//vector的下标从0开始
for (int i = 0; i < v1.size(); ++i) {
printf("%d ", v1[i]);
}
for (int i = 0; i < v3.size(); ++i) {
printf("%d %d\n", v3[i].x, v3[i].y);
}
//c++11中的语法,依次遍历v1,x为当前遍历的v1的元素
for (auto x: v1) {
printf("%d ", x);
}
for (auto x: v3) {
printf("%d %d\n", x.x, x.y);
}
return 0;
}
程序输出
v1.size() = 5
1 2 3 4 5 1 1
2 4
3 9
4 16
5 25
1 2 3 4 5 1 1
2 4
3 9
4 16
5 25
其他的一些操作
// 清空vector
v1.clear();
// empty()函数,返回一个bool类型,vector是否为空
if (v1.empty()) printf("已经清空嘞\n");
// size()函数,返回一个size_t类型(一个非负整数类型),vector的元素个数
printf("%d\n", v1.size());
// back()函数,返回vector容器中最后一个元素的值(v1[v1.size() - 1])也能实现
printf("%d\n", v1.back());
// front()函数,返回vector容器中第一个元素的值(v1[0])也能实现
printf("%d\n", v1.front());
sort函数
sort是STL中用于排序的函数。
排序时大小相同的元素可能会交换。
头文件
#include<algorithm>
升序排序
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[7] = { 11, 4, 5, 1, 41, 91, 98 };
// 对a数组中的[0, 7)左闭右开区间进行从小到大排序
sort(a, a + 7);
// 如果想要对[1, 7)从小到大排序则需要sort(a + 1, a + 7);
for (int i = 0; i < 7; ++i) printf("%d ", a[i]);
return 0;
}
降序排序
要上面程序中的a数组从大到小排序
法一
可以在原基础上增加一个参数
sort(a, a + 7, greater<int>());
法二
自定义一个cmp函数,充当第三个参数
#include <bits/stdc++.h>
using namespace std;
bool cmp(int a, int b) {
return a > b;
}
int main() {
int a[7] = { 11, 4, 5, 1, 41, 91, 98 };
// 对a数组中的[0, 7)左开右闭区间进行从大到小排序
vector <int> v = { 11, 4, 5, 1, 41, 91, 98 };
sort(a, a + 7, cmp);
// 注意vector的排序如何操作
sort(v.begin(), v.end(), cmp);
for (int i = 0; i < 7; ++i) printf("%d ", a[i]);
printf("\n");
for (int i = 0; i < 7; ++i) printf("%d ", v[i]);
return 0;
}
法三
如果只用到一个sort函数,写cmp有点麻烦。可以运用c++11的特性,写一个lambda函数嵌入sort函数内。
#include <bits/stdc++.h>
using namespace std;
int main() {
int a[7] = { 11, 4, 5, 1, 41, 91, 98 };
// 对a数组中的[0, 7)左开右闭区间进行从大到小排序
// 不用理解什么是lambda函数,照着写即可
sort(a, a + 7, [](int a, int b) {
return a > b;
});
for (int i = 0; i < 7; ++i) printf("%d ", a[i]);
return 0;
}
输出
98 91 41 11 5 4 1
对结构体排序
程序无法直接给两个结构体变量判断大小,因此无法直接排序。
如果想要对结构体排序有一下几个方法
法一
自定义一个cmp函数,充当第三个参数(类似降序排序)
#include <bits/stdc++.h>
using namespace std;
struct student {
int id; // 学生的学号
int ch; // 学生的语文成绩
int ma; // 学生的数学成绩
} a[10];
bool cmp(student a, student b) {
// 语文成绩高排前面
// 语文成绩相同,数学排前面
return (a.ch > b.ch) || (a.ch == b.ch && a.ma > b.ma);
}
int main() {
a[1] = { 1, 87, 86 };
a[2] = { 2, 87, 90 };
a[3] = { 3, 90, 0 };
a[4] = { 4, 86, 100 };
a[5] = { 5, 99, 99 };
sort(a + 1, a + 6, cmp);
for (int i = 1; i <= 5; ++i) {
printf("%d: %d %d\n", a[i].id, a[i].ch, a[i].ma);
}
return 0;
}
输出
5: 99 99
3: 90 0
2: 87 90
1: 87 86
4: 86 100
法二
同样可以利用lambda函数将cmp嵌入sort中。
#include <bits/stdc++.h>
using namespace std;
struct student {
int id; // 学生的学号
int ch; // 学生的语文成绩
int ma; // 学生的数学成绩
} a[10];
int main() {
a[1] = { 1, 87, 86 };
a[2] = { 2, 87, 90 };
a[3] = { 3, 90, 0 };
a[4] = { 4, 86, 100 };
a[5] = { 5, 99, 99 };
sort(a + 1, a + 6, [](student a, student b) {
return (a.ch > b.ch) || (a.ch == b.ch && a.ma > b.ma);
});
for (int i = 1; i <= 5; ++i) {
printf("%d: %d %d\n", a[i].id, a[i].ch, a[i].ma);
}
return 0;
}
法三
重载运算符。
程序无法判断两个结构体变量的大小,那我们就定义结构体的大小。
#include <bits/stdc++.h>
using namespace std;
struct student {
int id; // 学生的学号
int ch; // 学生的语文成绩
int ma; // 学生的数学成绩
// 这是一个特殊的函数,函数名为operator<
// 如果你不明白const关键字的意思,忽略即可
bool operator <(const student b) const {
return (ch < b.ch) || (ch == b.ch && ma < b.ma);
}
bool operator >(const student b) const {
return (ch > b.ch) || (ch == b.ch && ma > b.ma);
}
} a[10];
/*
可以把重载运算符函数写外面,写法是这样的,但不推荐
bool operator <(const student a, const student b) {
return (a.ch < b.ch) || (a.ch == b.ch && a.ma < b.ma);
}
*/
int main() {
a[1] = { 1, 87, 86 };
a[2] = { 2, 87, 90 };
a[3] = { 3, 90, 0 };
a[4] = { 4, 86, 100 };
a[5] = { 5, 99, 99 };
// 重载运算符,定义了student的<,就可以进行大小判断了
// 可以自行了解重载运算符,这里不再赘述
if (a[1] < a[2]) printf("OHHHHH!!!!\n");
sort(a + 1, a + 6);
for (int i = 1; i <= 5; ++i) {
printf("%d: %d %d\n", a[i].id, a[i].ch, a[i].ma);
}
printf("\n");
// 重载运算符后student可以像int一样操作了
sort(a + 1, a + 6, greater<student>());
for (int i = 1; i <= 5; ++i) {
printf("%d: %d %d\n", a[i].id, a[i].ch, a[i].ma);
}
return 0;
}
输出
OHHHHH!!!!
4: 86 100
1: 87 86
2: 87 90
3: 90 0
5: 99 99
5: 99 99
3: 90 0
2: 87 90
1: 87 86
4: 86 100
priority_queue
优先队列,可以在O(logN)的时间复杂度内实现添加元素,查找最值,删除最值。
头文件
#include <queue>
创建优先队列
priority_queue <int> Q1; //不写相关参数默认查找的是最大值
/*
三个参数分别为:
1.优先队列中存放的数据类型
2.存储数据的容器类型(填vector就行了)
3.比较函数(less找最大 greater找最小)
*/
priority_queue < int, vector<int>, less<int> > Q2; // 默认参数版,和上一行一致
priority_queue < int, vector<int>, greater<int> > Q3; // 查找最小值的优先队列
使用示例
#include <bits/stdc++.h>
using namespace std;
int main() {
priority_queue <int> Q;
// 给优先队列添加一个元素
Q.push(1);
Q.push(2);
Q.push(3);
Q.push(9);
// empty()函数,返回一个bool类型的值,表示优先队列是否为空
while (!Q.empty()) {
// top()函数,返回优先队列最值
printf("%d\n", Q.top());
// 删除优先队列的最值
Q.pop();
}
return 0;
}
数据类型为结构体的优先队列
参考sort函数部分,给结构体重载运算符即可。
#include <bits/stdc++.h>
using namespace std;
struct student {
int id; // 学生的学号
int ch; // 学生的语文成绩
int ma; // 学生的数学成绩
// 这是一个特殊的函数,函数名为operator<
// 如果你不明白const关键字的意思,忽略即可
bool operator <(const student b) const {
return (ch < b.ch) || (ch == b.ch && ma < b.ma);
}
bool operator >(const student b) const {
return (ch > b.ch) || (ch == b.ch && ma > b.ma);
}
} a[10];
/*
可以把重载运算符函数写外面,写法是这样的,但不推荐
bool operator <(const student a, const student b) {
return (a.ch < b.ch) || (a.ch == b.ch && a.ma < b.ma);
}
*/
int main() {
a[1] = { 1, 87, 86 };
a[2] = { 2, 87, 90 };
a[3] = { 3, 90, 0 };
a[4] = { 4, 86, 100 };
a[5] = { 5, 99, 99 };
// 一个查找最小值的优先队列
priority_queue < student, vector<student>, greater<student> > Q;
for (int i = 1; i <= 5; ++i) {
Q.push(a[i]); // 添加新元素
}
printf("Q.size() = %d\n", Q.size()); // 优先队列中元素的个数
while (!Q.empty()) { // Q.empty()判断优先队列是否为空
student tp = Q.top(); // 查找优先队列的最值
Q.pop(); // 删除最值
printf("%d: %d %d\n", tp.id, tp.ch, tp.ma); // 输出学生信息
}
return 0;
}
一些好用的函数
max(a, b); // 参数为两个相同类型的变量,返回最大值
min(a, b); // 参数为两个相同类型的变量,返回最小值
__gcd(a, b); // 参数为两个相同类型的整型变量,返回最大公约数
swap(a, b); // 参数为两个相同类型的变量,无返回值,交换两个变量的值