第二十四章:结构体与排序

 结构体与排序

学习结构体与排序之前,请确保你已掌握一维数组和函数的相关知识。

一、为什么要使用结构体

回顾前面的知识,我们都知道,数组可以用来批量定义和操控具有相同数据类型的变量。比如,int a[10]这条语句中,a数组可以存储10个int 类型的变量。

但是

如果需要批量定义的变量数据类型不同呢?比如:要同时统计一个班上所有学生的信息,包括姓名(string),年龄(int),身高(float),等等。这个时候,如果还用数组来存储信息的话,我们需要至少3个数组,处理起来很不方便,这时就要用到结构体。

结构体是 自定义类型 ,它就像一个 能装不同数据类型 的“包裹”。当你声明一个结构体后,需要赋予这个结构体一个名字(即 结构体名 )。而 定义具体变量时,也可以定义结构体数组 。这相当于告诉计算机,你一口气定义了许多“包裹”,每一个“包裹”里面都可以装入许多不同或相同数据类型的变量。

举个例子

朱老师得知拓拓是个编程高手,就交给了他一个 小任务

利用已学过的数组知识,拓拓很快就解决了这个问题。他建立了五个数组,分别存储每个学生的各项信息。程序如下:

#include
using namespace std;
string name[101];
char sex[101]; 
int age[101];
float score[101],height[101];
int main()
{int n;cin >> n;for(int i=1;i<=n;i++){cin>>name[i]>>sex[i]>>age[i]>>score[i]>>height[i];}for(int i=n;i>=1;i--){cout<

Copy

但拓拓觉得这样写太麻烦了,而且一个人的信息保存在不同的数组中,调用时容易出现错误,且效率很低。这时,大佬提醒拓拓,可以用结构体来存储不同数据类型的信息。于是,他花了一点儿时间自学,很快将学生信息用结构体更清晰地表示了出来。

二、结构体的基本操作

1.结构体的声明

使用结构体前,需要先声明一个结构体类型,再进行定义和使用。结构体类型的声明格式为:

struct 结构体类型名{     //其中,sruct是关键字,在c++中表示结构体数据类型 成员变量1;    //多个成员变量可以具有不同的数据类型数据类型 成员变量2;......
};

Copy

声明之后,就可以定义结构体变量了,格式如下:

结构体类型名 变量名;(struct 可省略)  

Copy

例如

我们需要表示一个学生的信息,首先我们声明学生的结构体:

struct student{   //student表示结构体的类型名string name;char sex;int age;float height,score;
};

Copy

然后定义一个具体的学生:

student zhangsan;//声明一个student的结构体变量叫zhangsan

Copy

当然我们如果需要很多学生,可以声明为结构体数组:

student a[1001];//创建结构体数组a
//a数组中的每一个元素都是一个结构体类型student的变量

Copy

另外

为方便起见,我们一般直接在声明结构体的同时定义变量,格式如下:

struct 结构体类型名{     //其中,sruct是关键字,在c++中表示结构体数据类型成员变量1; //多个成员变量可以具有不同的数据类型数据类型成员变量2;......
}结构体变量表;

Copy

比如:

struct student{string name;  char sex;int age;   float height,score;
}a[1001];

Copy

2.结构体的使用

(1)将结构体变量视为一个整体进行操作,例如:

swap(a[1], a[2]);  

Copy

(2)使用符号“.”对结构体变量的成员进行操作,“.”的含义可以理解为中文的“的”,格式为:

结构体名.成员变量名

Copy

比如:

student  a;//李四cin >> a.name;//输入赋值李四的名字a.age = 23;//直接赋值给李四的年龄为23

Copy

3.结构体的初始化

(1)集合形式,比如:

student  a = {"tuotuo",'F',12,168,100};

Copy

(2)逐一赋值,比如:

student  a;
cin >> a.name >> a.sex;
a.age = 12;

Copy

三、结构体排序

1.sort()函数

在前面的学习中,我们已经接触了各种排序算法,比如选择排序、冒泡排序、插入排序、桶排序、sort()等。其中,sort()函数是使用起来篇幅最短的排序方式。

使用sort()的基本格式为:

sort(首元素地址,尾元素地址的下一项,比较函数);

Copy

在sort()函数的三个参数中,前两个是必填的,第三个 比较函数 可以没有,默认按照从小到大的顺序排序。一般来说,对于基本数据类型,如int、long long int 、double、float、char等,可以用两个参数的sort函数非常方便地实现递增排序,比如:

int a[6] = { 6,5,4,3,2,1};
sort(a,a+6);
for( int i=0; i<6; i++) cout<

Copy

其运行结果为:

1 2 3 4 5 6

Copy

2.一维数组的sort()函数

有时候题目要求从大到小排序,或者对结构体这样自定义类型进行排序,此时就要用到函数sort()的第三个参数 比较函数 。

首先我们定义一个bool类型的cmp()函数用于排序。只要在调用时将函数指针cmp写在sort函数的第三个参数的位置即可。

定义函数cmp()的示例如下:

bool cmp(int a, int b)
{    return a>b;
}

Copy

调用时,只需要写入第三个参数即可,注意不需要括号,如下:

int a[6] = {2,3,4,5,1,7};
sort(a, a+6, cmp);
for( int i=0; i<6; i++)cout<

Copy

其运行结果为:

7 5 4 3 2 1

Copy

3.结构体中的sort()函数

现在给你一个结构体,现在有这样一个要求:按照年龄从小到大输出。

那我们就照结构体中成员变量age(也就是年龄)进行从小到大的排序,代码如下:

struct student {string name;    int age;    float height;
}a[10];
bool cmp(student a, student b){    return  a.age < b.age;
}
int main(){    ...//输出        sort(a, a + n, cmp);//按照年龄从小到大排序        ...//输出
}

Copy

四、例题

1.成绩排序

【题目描述】

输入N个学生的姓名、性别、和语文、数学的得分,按语文从高到低输出,语文一样的按数学成绩从高到低输出。性别用(female,male)表示。

【输入格式】

第1行,有一个整数N,N的范围是[1…100];
下面有N行,每行一个 姓名,性别,2个整数。2个整数分别代表该学生的语文和数学的得分。
姓名由不超过10个的小写字母组成,整数范围[1…100]

【输出格式】

总分排序后的名单,共N行,每行格式:姓名 性别 语文 数学 用空格隔开。

基本思路

输入,之后按照题目的要求排序,最后输出即可。

参考代码如下:

#include
using namespace std;struct student
{string xm;//姓名 string xb;//性别 int yw;//语文 int sx;//数学 
};
student s[101];bool cmp(student s1, student s2)
{if(s1.yw != s2.yw)//语文不同,按照语文从高到低排序return s1.yw > s2.yw;else//语文相同,按照数学从高到低排序return s1.sx > s2.sx;
}int main()
{int n;cin>>n;for(int i=0;i>s[i].xm>>s[i].xb>>s[i].yw>>s[i].sx;}sort(s,s+n, cmp);//排序for(int i=0;i

Copy

2.特殊的成绩排序

【题目描述】

输入N个学生的姓名和语文、数学的得分,按总分从高到低输出。分数相同的按输入先后输出。

【输入格式】

第1行,有一个整数N,N的范围是[1…100];
下面有N行,每行一个 姓名,2个整数。2个整数分别代表该学生的语文和数学的得分。
姓名由不超过10个的小写字母组成,整数范围[1…100]

【输出格式】

总分排序后的名单,共N行,每行格式:姓名 语文 数学 总分,用空格隔开。

【输入样例】

4
qqq 10 10
www 10 20
eee 15 10
rrr 19 1

Copy

【输出样例】

www 10 20 30
eee 15 10 25
qqq 10 10 20
rrr 19 1 20

Copy

基本思路

和上一题类似,输入,排序,然后输出。

但是总分怎么办?输入先后顺序怎么处理?

遇到这种问题,可以在结构体定义的时候,添加相应的变量。

比如添加总分变量和顺序变量

struct stu
{string mz;//名字int yw;//语文 int sx;//数学 int zf;//总分 int id;//输入的序号
};

Copy

那这两个变量怎么放进来呢?可以 在输入的时候就放进来

for(int i = 1; i <= n; i++)
{cin >> s[i].mz >> s[i].yw >> s[i].sx;s[i].zf = s[i].yw + s[i].sx;//输入的时候可以计算总分s[i].id = i;//把i当成序号记录一下
}

Copy

最后实现一下比较函数即可。

参考代码如下:

#include 
using namespace std;
struct stu
{string mz;//名字int yw;//语文 int sx;//数学 int zf;//总分 int id;//输入的序号
};
bool cmp(stu s1, stu s2)//比较两个人的情况 
{if(s1.zf != s2.zf)//总分不等,则按照总分从大到小排序return s1.zf > s2.zf;else//总分相等,按照输入顺序从小到大排序return s1.id < s2.id;
}
int main()
{stu s[101];//结构体数组sint n;cin >> n;for(int i = 1; i <= n; i++){cin >> s[i].mz >> s[i].yw >> s[i].sx;s[i].zf = s[i].yw + s[i].sx;//输入的时候可以计算总分s[i].id = i;//把i当成序号记录一下}sort(s+1, s+n+1, cmp);//结构体需要自定义比较方式 for(int i = 1; i <= n; i++)cout << s[i].mz << " " << s[i].yw << " " << s[i].sx << " " << s[i].zf << endl;
}

Copy

五、练习

成绩排序

高校录取

谁拿了最多奖学金

年龄排序

奖学金

植树积分

拓尔思学员合影

生日相同问题

颠倒排序

德才论


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章