结构体排序(多关键字排序)

简要阐述:

在解决问题的时候,经常会有一些排序问题。一般采用冒泡排序、插入排序,或者利用sort函数排序
就能解决。但是遇到多关键字的排序,自己写排序算法就可能会挺麻烦的,这里就要利用sort函数。
多关键字排序中sort()函数和结构体的使用:

1、在结构体中重载比较符" < "struct node{ 
	int a,b,c;
	bool operator < (const node &n) const{ 
		if(a!=n.a) return a>n.a;//第一关键字降序
		if(b!=n.b) return b<n.b;//第二关键字升序
		return c>n.c;//第三关键字降序
	}
};
2.定义sort函数中的cmp:

bool cmp(const node &n1,const node &n2)
{ 
	if(n1.a!=n2.a) return n1.a>n2.a;//第一关键字降序
	if(n1.b!=n2.b) return n1.b<n2.b;//第二关键字升序
	return n1.c>n2.c;//第三关键字降序
}
//使用sort(node_array,node_array+n,cmp) 就可以对数组node_array排序。
3.结合lambda匿名函数使用,直接在sort()里面写lambda函数:

sort(node_array,node_array+n,[](node &n1,node &n2)->bool{ 
	if(n1.a!=n2.a) return n1.a>n2.a;//第一关键字降序
	if(n1.b!=n2.b) return n1.b<n2.b;//第二关键字升序
	return n1.c>n2.c;//第三关键字降序
};

具体问题:

例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。

输入:
输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状,其描述采用问题描述中的数量标记的格式,见上面的表格。

输出:
根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再 按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。

8 20
GuGuDong 96 -3 40(3) 0 0 1 -8 0
hrz 107 67 -3 0 0 82 0 0
TT 120(3) 30 10(1) -3 0 47 21(2) -2
OMRailgun 0 -99 -8 0 -666 -10086 0 -9999996
yjq -2 37(2) 13 -1 0 113(2) 79(1) -1
Zjm 0 0 57(5) 0 0 99(3) -7 0

问题分析:

1.首先是多关键字排序:
第一关键字:AC题数,降序排序
第二关键字:时间(罚时多少),升序排序
第三关键字:名字字典排序,升序排序。

2.然后就是 12(30) 这样的形式如何分开成两个数字读入。
这里介绍一个sscanf()函数,用法和scanf()差不多,只不过读入的是字符串。
char score[20];
scanf(“%s”,score);
int t,f;
int res=sscanf(score,”%d(%d)”,&t,&f);

这样,第一个数字读入t,第二个数字读入f。
res=1表示只有一个数字;res=2表示有两个数字。

所有代码

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct person
{ 
	char na[20];
	int sum_count;
	int penalty;
	
}a[10000];

bool cmp(const person &a,const person &b)
{ 
	if(a.sum_count!=b.sum_count)
		return a.sum_count>b.sum_count;
	if(a.penalty!=b.penalty)
		return a.penalty<b.penalty;
	return strcmp(a.na,b.na)<0;
}
int main()
{ 
	int T,pe,count,sum_pe,time[2],flag;
	scanf("%d %d",&T,&pe);
	int renshu=0;
	while(scanf("%s",a[renshu].na)!=EOF)
	{ 
		count=0;
		sum_pe=0;
		for(int i=0;i<T;i++)
		{ 
			char score[20];
			scanf("%s",score);
			int t,f;
   			int res=sscanf(score,"%d(%d)",&t,&f);
			if(res==2)//如果读取到两个数
			{ 
				count++;
				sum_pe=sum_pe+t+f*pe;
			}
			else if(res==1)//如果读取到一个数
			{ 
				if(t>0)
				{ 
					count++;
					sum_pe=sum_pe+t;
				}
			}
		}
		a[renshu].penalty=sum_pe;
		a[renshu].sum_count=count;
		renshu++;
	}
	sort(a,a+renshu,cmp);
	for(int i=0;i<renshu;i++)
	{ 
		printf("%-10s %2d %4d\n",a[i].na,a[i].sum_count,a[i].penalty);
	}
	return 0;
}

    原文作者:✘万里长梦
    原文地址: https://blog.csdn.net/qq_45029327/article/details/104647717
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞