结构体

结构体可以看作是一系列元素组合的组合体,也可以理解为是自定义的数据类型,且该类型中可以存储多种数据。

1.定义结构体

一个结构体的定义示例,如下所示:

struct Student {
	int value;
	double weight;
	string name;
};  // 注意这个分号!这里其实也可以定义结构体的变量、数组

Student s1;   // 定义了Student类型的一个变量
Student s2[105];  // 定义了Student类型的一个数组

上面定义了一个名为 Student 的结构体,三个成员元素 value, weight, name,类型分别是 int, double, string

后续定义了 Student 类型的变量 s1 和 数组 s2,其实还可以定义常量、指针等等,普通数据类型可以做到的事,结构体类型也是可以做到的。

对于结构体类型定义出来的变量,可以理解为其一个变量中就记录了多个信息,比如 s1 里面就有三个数据,并且这些数据可以是不同类型的。

另外,一般结构体的类型名,为了区分一般是首字母大写。

2.访问/修改成员元素

可以通过 变量名.成员元素名 来访问指定成员元素,例如在上例中,可以使用 cout << s1.value; 来输出 s1 中的 value 元素,这些元素的使用场景和普通变量一样,只是写法有所不同而已。

结构体数组也是一样的,加上下标即可,下面是简单演示:

#include <bits/stdc++.h>
using namespace std;

struct Student {
	int value;
	double weight;
	string name;
};

Student s1;   // 定义了Student类型的一个变量
Student s2[105];  // 定义了Student类型的一个数组

double sum = 0;

int main() {
    cin >> s1.value >> s1.weight >> s1.name;
    cout << s1.name << " " << s1.weight << '\n';

	for (int i=1; i<=10; i++) {
		cin >> s2[i].value >> s2[i].weight >> s2[i].name;
		sum += s2[i].weight;
	}
	cout << sum;
	return 0;
}

3.结构体的应用场景

其实很多场景不使用结构体一样可以达成相同的效果,只是实现起来有的麻烦有的简单。

结构体的好处是可以把多个不同的元素捆绑在一起,其实这一功能多定义几个数组也可以实现,但用结构体就只需要定义一个数组了,减少了思考的难度。

另外,在后续学习一些算法,例如 排序、广度优先搜索、最短路 等等时,我们可能需要把好几个元素放在一起操作,例如交换、添加、删除等等,使用结构体可以让代码更清晰,避免过多的变量定义。

4.结构体排序

在函数章节我们学习了 sort 的使用,它可以对数组进行排序,那么对于结构体数组该如何进行排序呢?

需要注意的是,结构体是不会自带排序规则的(这个很好理解,一个结构体里常有好几个数据类型,那到底谁说了算呢),所以我们必须自定义排序规则,有两种方式:

1.外部定义比较函数

其实就是给 sort 自定义比较规则,注意 cmp 函数的类型应该是结构体类型即可:

#include <bits/stdc++.h>
using namespace std;

struct Student {
	int value;
	double weight;
	string name;
};

int n;
Student a[1005];

bool cmp(Student a1, Student a2) {
	return a1.weight > a2.weight;  // 按照 weight 从大到小排序
}

int main() {
	cin >> n;
	for (int i=1; i<=n; i++) cin >> a[i].name >> a[i].value >> a[i].weight;
	
	sort(a+1, a+1+n, cmp);
	
	for (int i=1; i<=n; i++) cout << a[i].name << " " << a[i].weight << '\n';
	return 0;
}

2.重载结构体的比较运算符

这一写法在后面偶尔会用得到,因为后续大量用到 STL 容器,如果把结构体作为容器存储的类型的话,例如堆,那么重载比较运算符会让使用 STL 变得简单。

#include <bits/stdc++.h>
using namespace std;

struct Student {
	int value;
	double weight;
	string name;
	
	// 这样重载,相当于在比较两个结构体变量谁更小时,就是在比较谁的 weight 更小
	bool operator < (const Student& other) const {
		return weight < other.weight;
	}
};

int n;
Student a[1005];

int main() {
	cin >> n;
	for (int i=1; i<=n; i++) cin >> a[i].name >> a[i].value >> a[i].weight;
	
	sort(a+1, a+1+n);
	
	for (int i=1; i<=n; i++) cout << a[i].name << " " << a[i].weight << '\n';
	return 0;
}

5.课上例题

培训

旗鼓相当的对手

最厉害的学生

奖学金

谁拿了最多奖学金

区间合并

高考组题

她来听我的演唱会

练习

风的召唤

数字黑洞

风铃

原神,启动!

john爱听歌

酒店

01串排序