宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”
现给出一批考生的德才分数,请根据司马光的理论给出录取排名。
输入格式:
输入第一行给出 3 个正整数,分别为:N(≤105),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到优先录取线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于 H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。
随后 N 行,每行给出一位考生的信息,包括:准考证号、德分、才分,其中准考证号为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。
输出格式:
输出第一行首先给出达到最低分数线的考生人数 M,随后 M 行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。
经过:
今天数据结构实验课的题目,乍一看感觉挺简单,思路就是先对所有合格考生的总分从小到大排序,这个过程可以使用快速排序实现;再根据四个分数标准把排好序的数据分成四类,遇到同类且总分相同的则比较德育分,德育分相同再按准考证号升序,这个过程可以采用链表,在链表插入过程中再对同总分的数据进一步排序,可采用插入排序实现,因为此时数据基本有序,插入排序在这种情况下时间复杂度较小,比较适合。
很快啊,代码就扣出来了,最近考试周要来了,事挺多,所以实验课要速战速决!必须立刻拿下!提交!
哎咋回事啊?(经过漫长的debug)哦双向链表忘了改后继结点的前驱指针了
改好,提交!
哎咋又超时了 ?(经过漫长的debug)哦遍历时把前导和后随指针的起始点都设在链表的尾节点上了,结果尾插的时候插成闭环了😰。
改好,提交!
赢了!然而一抬头天都黑完了😓,明天大物小测还没复习,感觉要寄😓。
太晚了,先开睡,明天的明天再说!💤
参考代码:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//定义存储考生考号和分数的结构体
typedef struct SCORE{
char num[9];
int d, c;
}INFO;
//定义链表
typedef struct CHAINLISTNODE{
struct SCORE item;
struct CHAINLISTNODE *next;
struct CHAINLISTNODE *before;
} CLN,*CLNptr;
typedef struct CHAINLIST{
CLNptr head;
CLNptr rear;
} CL;
void push(CL *cl,INFO ins){//链表插入操作,插入时对总分相同的依次按德育分降序和学号升序进行排序
CLNptr p = (CLNptr)malloc(sizeof(CLN));
CLNptr tra = cl->rear,ptra=NULL;
while(tra->before&&tra->item.c+tra->item.d==ins.c+ins.d&&tra->item.d<ins.d){
ptra = tra;
tra = tra->before;
}
while(tra->before&&tra->item.c+tra->item.d==ins.c+ins.d&&tra->item.d==ins.d&&strcmp(tra->item.num,ins.num)>0){
ptra = tra;
tra = tra->before;
}
p->before = tra;
p->next = tra->next;
p->item = ins;
tra->next = p;
if(ptra)ptra->before = p;
if(tra==cl->rear)cl->rear = p;
}
CL init(){//链表初始化操作
CLNptr p = (CLNptr)malloc(sizeof(CLN));
p->next = NULL;
p->before = NULL;
CL cl;
cl.head = p;
cl.rear = p;
return cl;
}
void traverse(CL cl){//链表遍历输出
CLNptr p = cl.head->next;
while(p!=NULL){
printf("%s %d %d\n", p->item.num, p->item.d, p->item.c);
p = p->next;
}
}
//快速排序
void T(INFO *x,INFO *y){
INFO tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
int partition(INFO *list,int left,int right){
INFO key = list[left];
while (left<right){
while (left<right&&list[right].c+list[right].d<=key.c+key.d)--right;
T(list + left, list + right);
while (left<right&&list[left].c + list[left].d>=key.c+key.d)++left;
T(list + left, list + right);
}
T(list + left, &key);
return left;
}
void quicksort(INFO *list,int left,int right){
if(left<right){
int mid = partition(list, left, right);
if(left<mid-1)quicksort(list, left, mid - 1);
if(right>mid+1)quicksort(list, mid + 1, right);
}
}
int main(){
int n, L, H;
scanf("%d%d%d", &n, &L, &H);
INFO *list = (INFO *)malloc(sizeof(INFO) * n);
int len = 0;
for (int i = 0; i < n;++i){
int d, c;
char num[9];
scanf("%s%d%d", num, &d, &c);
if(d>=L&&c>=L){
strcpy(list[len].num, num);
list[len].c = c;
list[len].d = d;
++len;
}
}
quicksort(list, 0, len - 1);
CL level[4];//对四个类别建桶
for (int i = 0; i < 4;++i){
level[i] = init();
}
for (int i = 0; i < len;++i){
if(list[i].d>=H){
if(list[i].c>=H){//德才兼备入桶0
push(level + 0, list[i]);
}
else{//德胜才入桶1
push(level + 1, list[i]);
}
}
else{
if(list[i].c<H&&list[i].d>=list[i].c){//才德兼亡但尚有德胜才入桶2
push(level + 2, list[i]);
}
else{//其余入桶3
push(level + 3, list[i]);
}
}
}
printf("%d\n", len);
for (int i = 0; i < 4;++i){
traverse(level[i]);
}
return 0;
}
又
c语言标准库好像有自带快速排序,刚刚才知道🐊🐊
用qsort重写一遍:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct SCORE{
char num[9];
int d, c, sum, level;
}*ptr;
int compare(const void *X,const void *Y){
ptr x = (ptr)X, y = (ptr)Y;
if(x->level<y->level){
return -1;
}
else if(x->level==y->level){
if(x->sum>y->sum){
return -1;
}
else if(x->sum==y->sum){
if(x->d>y->d){
return -1;
}
else if(x->d==y->d){
if(strcmp(x->num,y->num)<0){
return -1;
}
}
}
}
return 1;
}
int main(){
int n, L, H;
scanf("%d%d%d", &n, &L, &H);
ptr list = (ptr)malloc(sizeof(struct SCORE) * n);
int len = 0;
for (int i = 0; i < n;++i){
int d, c;
char num[9];
scanf("%s%d%d", num, &d, &c);
if(d>=L&&c>=L){
strcpy(list[len].num, num);
list[len].c = c;
list[len].d = d;
list[len].sum = c + d;
if(c>=H&&d>=H){
list[len].level = 0;
}
else if(d>=H){
list[len].level = 1;
}
else if(d>=c){
list[len].level = 2;
}
else{
list[len].level = 3;
}
++len;
}
}
qsort(list, len, sizeof(struct SCORE), compare);
printf("%d\n",len);
for (int i = 0; i < len;++i){
printf("%s %d %d\n", list[i].num, list[i].d, list[i].c);
}
return 0;
}