Problem Description
建立一个学生信息系统,输入学生信息,输出有挂科同学的信息,再按照平均成绩从高到低排序输出。
Input
首先输入学生的个数N,在接下来的N行,每行输入由学生姓名(小写拼音),第一科成绩、第二科成绩、第三科成绩以及总分构成。
Output
首先输出学科中有挂科的同学信息,并将其姓名和单科成绩以如下格式输出:
*[qianer] 65 32 77
然后按照平均成绩由高到低,输出所有同学姓名和单科成绩。
Sample Input
5
zhaoyi 70 80 90 240
qianer 65 32 77 174
sunsan 100 55 68 223
lisi 86 77 90 253
wangwu 100 59 66 225
Sample Output
*[qianer] 65 32 77
*[sunsan] 100 55 68
*[wangwu] 100 59 66
lisi 86 77 90 253
zhaoyi 70 80 90 240
wangwu 100 59 66 225
sunsan 100 55 68 223
qianer 65 32 77 174
解题思路
- 定义学生类型结构体,其中包含姓名,第一、二、三科成绩,总分以及是否挂科。
- 声明students数组,录入学生数据,并通过第一、二、三科成绩判断该生是否挂科。
- 输出挂科学生信息,即结构体数组元素成员变量中isFailed值为true的元素。
- 默写快排代码模板,改为以总分划分数组,对students数组按照总分降序排序(算法笔记p142快速排序)。
- 打印排序后的学生信息。
经验总结
- 生成随机数需加头文件stdlib.h、time.h和math.h。
- srand((unsigned) time(NULL))用于初始化随机种子(记住就行)。
- rand()函数生成[0,RAND_MAX]范围内的随机数,然后用这个随机数除以RAND_MAX得到一个[0,1]范围内的浮点数;用这个浮点数乘以(right - left),加上left,再用round()函数四舍五入后,得到[left,right]范围内的随机数;这个浮点数相当于[left,right]范围内的比例位置。
- 例:rand()生成的随机数经过处理得到浮点数为0.5,left = 2,right = 5,right - left = 3,3 * 0.5 = 1.5,1.5 + 2 = 3.5,round(3.5) = 4,得到[2,5]范围内的随机数4。
代码实现(C)
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#define MaxSize 1000
typedef struct Student {
char name[20];
int score[3];
int sum;
bool isFailed; // 用于记录该生是否挂科
} Student;
Student students[MaxSize];
// 输入数据并记录是否挂科
void input(int N, int *score) {
for (int i = 0; i < N; ++i) {
// 输入姓名
scanf("%s", students[i].name);
// 输入各科成绩
for (int j = 0; j < 3; ++j) {
scanf("%d", score);
students[i].score[j] = *score;
}
// 输入总分
scanf("%d", &students[i].sum);
// 判断是否挂科
for (int j = 0; j < 3; ++j) {
if (students[i].score[j] < 60) {
students[i].isFailed = true;
break;
}
students[i].isFailed = false;
}
}
}
// 打印挂科学生信息
void printFailed(int N) {
for (int i = 0; i < N; ++i)
if (students[i].isFailed)
printf("*[%s] %d %d %d\n", students[i].name, students[i].score[0], students[i].score[1],
students[i].score[2]);
}
// 交换学生信息
void swap(int left, int pivotIndex) {
Student pivot = students[pivotIndex];
students[pivotIndex] = students[left];
students[left] = pivot;
}
// 选取随机枢轴,对区间[left, right]进行划分
int randPartition(int left, int right) {
// 初始化随机种子
srand((unsigned) time(NULL));
// 生成[left, right]内的随机数pivotIndex作为枢轴
int pivotIndex = (int) round(1.0 * rand() / RAND_MAX * (right - left) + left);
// 交换students[left]与枢轴元素
swap(left, pivotIndex);
// 以随机枢轴划分数组
Student temp = students[left];
while (left < right) {
while (left < right && students[right].sum <= temp.sum) right--;
students[left] = students[right];
while (left < right && students[left].sum > temp.sum) left++;
students[right] = students[left];
}
students[left] = temp;
return left;
}
// 快速排序
void quick_sort(int left, int right) {
if (left < right) {
int pos = randPartition(left, right);
quick_sort(left, pos - 1);
quick_sort(pos + 1, right);
}
}
// 打印学生信息
void printInfo(int N) {
for (int i = 0; i < N; ++i)
printf("%s %d %d %d\n", students[i].name, students[i].score[0], students[i].score[1], students[i].score[2]);
}
int main() {
int N, score;
while (~scanf("%d", &N)) {
// 录入学生数据并记录挂科学生信息
input(N, &score);
// 打印挂科学生信息
printFailed(N);
// 对学生按照总分降序排序
quick_sort(0, N - 1);
// 打印学生信息
printInfo(N);
}
return 0;
}