算法笔记刷题(1)——排序算法之PAT Ranking

129 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

本篇博客是对自己对在《算法笔记》这本书中刷题的一些总结和收获。今天我将对一道排序算法题进行讲解和总结。

题目

1025 PAT Ranking

Programming Ability Test (PAT) is organized by the College of Computer Science and Technology of Zhejiang University. Each test is supposed to run simultaneously in several places, and the ranklists will be merged immediately after the test. Now it is your job to write a program to correctly merge all the ranklists and generate the final rank.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive number N (≤100), the number of test locations. Then N ranklists follow, each starts with a line containing a positive integer K (≤300), the number of testees, and then K lines containing the registration number (a 13-digit number) and the total score of each testee. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first print in one line the total number of testees. Then print the final ranklist in the following format:

registration_number final_rank location_number local_rank

The locations are numbered from 1 to N. The output must be sorted in nondecreasing order of the final ranks. The testees with the same score must have the same rank, and the output must be sorted in nondecreasing order of their registration numbers.

Sample Input:

2
5
1234567890001 95
1234567890005 100
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85

Sample Output:

9
1234567890005 1 1 1
1234567890014 1 2 1
1234567890001 3 1 2
1234567890003 3 1 2
1234567890004 5 1 4
1234567890012 5 2 2
1234567890002 7 1 5
1234567890013 8 2 3
1234567890011 9 2 4

解析

这道题是一道英文题,翻译成中文意思大概是:有n个考场,每个考场有若干数量的考生。现在给出各个考场中考生的准考证号与分数,要求将所有考生按分数从高到低排序,并按顺序输出所有考生的准考证号、排名、考场号以及考场内排名。

因为涉及到的学生信息有很多,所以我们可以先用一个结构体来存储学生的各项信息,包括准考证号、分数、考场号以及考场内排名。为了方便排序,我们可以事先写一个排序函数,设置规则为:当分数不同则按照分数从高到低来排序,当分数相同则按照准考证号从小到大排序。
排序函数定义如下:

bool cmp(student a,student b){
	if(a.score!=b.score) return a.score > b.score;
	else return strcmp(a.id,b.id) < 0;
}

结构体定义如下:

struct student{
	char id[15]; //准考证号 
	int score; // 分数 
	int location_num;//考场号 
	int location_rank;//考场内排名 
}s[100000];

我们只需要按照以下步骤进行算法实现:

  1. 分考场依次读入各位考生的信息,按照排序规则(即上文提到的排序函数)对所有考生进行排序,然后把排名写入结构体中。
  2. 再对所有考场的考生进行排序。
  3. 最后按照要求输出排序结果。

代码展示

#include<bits/stdc++.h>
using namespace std;
struct student{
	char id[15]; //准考证号 
	int score; // 分数 
	int location_num;//考场号 
	int location_rank;//考场内排名 
}s[100000];

/*排序规则:按照分数从高到低进行排名,如果成绩相同,按照准考证号从小到大排名*/ 
bool cmp(student a,student b){
	if(a.score!=b.score) return a.score > b.score;
	else return strcmp(a.id,b.id) < 0;
}
int main(){
	int n,k,num=0;//n为考场数,k为考场内人数,num为总人数
	cin>>n;
	for(int i = 1;i<=n;i++){ //i为考场号 
		cin>>k;
		for(int j=0;j<k;j++){
			scanf("%s %d",s[num].id,&s[num].score);
			s[num].location_num = i; //i为考场号
			num++;
			
		}
		sort(s+num-k,s+num,cmp);//对一个考场的所有人成绩排序
		s[num-k].location_rank = 1;//把成绩π第一的排名设为1
		for(int j = num-k+1;j<num;j++){//对于该考场的剩余其他考生 
			if(s[j].score == s[j-1].score){
				s[j].location_rank = s[j-1].location_rank;
			}
			else{
				// location_rank为该考生前的人数
				s[j].location_rank = j-(num-k)+1;
			}
		} 
	}
	cout<<num<<endl;
	sort(s,s+num,cmp);
	int rank = 1;
	for(int i=0;i<num;i++){
		if(i>0&&s[i].score!=s[i-1].score){
			rank = i+1;//当前考生与上一个考生成绩不同,排名更新为人数+1
			 
		}
		printf("%s ",s[i].id);
		printf("%d %d %d\n",rank,s[i].location_num,s[i].location_rank);
		
	} 
	return 0;
}

总结


从今天开始,我将正式进入数据结构与算法的刷题练习,今天以一道PAT甲级的排序算法题作为开头,虽然题目很难,但是通过看题解理解之后也会发现其实核心还是对排序算法的理解和掌握。之后我将继续更新这一专栏,希望通过不停的练习,我的算法能力也可以得到有效提升,加油奥利给!