《算法笔记》4.1小节——算法初步->排序

简单选择排序
选择后面无序中最小的元素A[i]放在有序序列A[0]-A[i-1]的最后,让A[0]-A[i]是有序的。

void selectsort(){
for (int i = 1; i <= n; i++)
	{
		int k = i;
		for (int j = i;j <= n; j++)
		{
			if (A[j] < A[k])
			{
				k = j;
			}
		}
		int temp = A[k];
		A[k] = A[i];
			A[i] = temp;
	}
}

直接插入排序
从后向前枚举,让前面始终是有序的

int main()
{
	int A[7] = { 0,5,2,4,6,3,1 };
	int i,j;
	int temp;
	//下面排序A[1]-A[6]
	for (i = 2; i <= 6; i++)
	{
		//printf("%d---%d %d %d %d %d %d\n", i, A[1], A[2], A[3], A[4], A[5], A[6]);
		for (j = i; j >= 2; j--)
		{
			if (A[j-1] > A[j])
			{
				temp = A[j];
				A[j] = A[j-1];
				A[j-1] = temp;				
			}
		}		
	}
	//printf("%d %d %d %d %d %d\n",A[1],A[2],A[3],A[4],A[5],A[6]);
	return 0;
}

使用sort函数进行排序
注意结构体定义、strcmp函数、cmp函数以及排序后排名的计算
⭐⭐⭐PAT A1025 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.

  • 输入
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.
第一行是人数N,下面有N个用例,下面是K,表示该用例有K个人,13位的考号以及总分。
  • 输出
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.
打印被测者的总数
然后输出考号,最终排名,考场号,本考场排名
  • 样例输入
2
5
1234567890001 95
1234567890005 100
1234567890003 95
1234567890002 77
1234567890004 85
4
1234567890013 65
1234567890011 25
1234567890014 100
1234567890012 85
  • 样例输出
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

这题其实主要考察的是sort函数,但是我卡在了一些逻辑上,总的来说难度不大,要注意细节,测试用例0和用例2有多个考点,测试用例1和3只有两个考点,多个考点的时候要注意循环里的变量是怎么变化的

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn =110;
int location[maxn];
struct student {
	char id[15];
	int score;
	int location_number;
	int location_rank;
	int final_rank;
}stu[30010];
//下面是用到的两个比较函数
bool cmp1(student a,student b) 
{
	if (a.score != b.score) return a.score > b.score;
	else return strcmp(a.id, b.id) < 0;
}
bool cmp2(student a, student b)
{
	if (a.location_number != b.location_number)return a.location_number < b.location_number;
	else if (a.score != b.score) return a.score > b.score;
	else return strcmp(a.id, b.id) < 0;
}
int main()
{
	int nums;//总考生数
	int N;//考场数
	int i, j;
	scanf("%d",&N);
	nums = 0;
	for (i = 1; i <=N; i++)
	{
		scanf("%d", &location[i]);//location[考场号]=考场人数		
		for (j = nums; j < nums+location[i]; j++)
		{
			scanf("%s %d",stu[j].id,&stu[j].score);
			stu[j].location_number = i;
		}
		nums += location[i];//计算总考试人数		
	}
	printf("%d\n",nums);//输出总人数	

	//上面输入完成所有考生的location_number,id和score的输入
	//下面进行排序输出
	//1.对各个考场进行排序
	//首先重排考场,首先按照考场号大小来拍,如果考场号大小相同按照成绩来排,如果成绩相同就按照考号来拍
	sort(stu, stu + nums, cmp2);
	/*printf("按照各个考场排序:\n");
	for (i = 0; i < nums; i++)
	{
		printf("%s %d %d\n", stu[i].id, stu[i].location_number, stu[i].score);
	}*/
	int temp = 0;
	location[0] = 0;
	int temp1=0;
	for (i = 1; i <= N; i++)//一共有N个考场
	{
		temp1 += location[i - 1];
		stu[temp1].location_rank = 1;//让当前考场成绩最高的学生排名第一
		temp += location[i - 1];//temp表示已经拍好序号的学生人数
		for (j = 1; j < location[i]; j++)
		{
			
				if (stu[j + temp].score == stu[j + temp - 1].score)
					stu[j + temp].location_rank = stu[j + temp - 1].location_rank;
				else
				{
					stu[j + temp].location_rank = j + 1;
				}			
		}		
	}
	//2.对总的人数进行排序	
	sort(stu, stu + nums, cmp1);	
	/*printf("按照总人数排序:\n");
	for (i = 0; i < nums; i++)
	{
		printf("%s %d\n", stu[i].id, stu[i].score);
	}*/
	stu[0].final_rank = 1;
	for (i = 1; i < nums; i++)
	{
		if (stu[i].score == stu[i - 1].score)
			stu[i].final_rank = stu[i - 1].final_rank;
		else
		{
			stu[i].final_rank = i + 1;
		}		
	}
	for (i = 0; i < nums; i++)
	{
		printf("%s %d %d %d\n",stu[i].id,stu[i].final_rank,stu[i].location_number,stu[i].location_rank);
	}
	return 0;
}

codeup100000581
问题 A: 排序
问题描述:对输入的n个数进行排序并输出。

  • 输入
输入的第一行包括一个整数n(1<=n<=100)。 接下来的一行包括n个整数。
  • 输出
可能有多组测试数据,对于每组数据,将排序后的n个整数输出,每个数后面都有一个空格。
每组测试数据的结果占一行。
  • 样例输入
5
5 4 3 1 2
  • 样例输出
5
5 4 3 1 2
#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
	int n;
	int a[110];
	int i;
	while (scanf("%d", &n) != EOF)
	{
		for (i = 0; i < n; i++)
		{
			scanf("%d", &a[i]);	
		}
		sort(a, a + n);
		for (i = 0; i < n; i++)
		{
			printf("%d ", a[i]);
		}
		printf("\n");
		memset(a, 0, sizeof(a));
	}
	
	return 0;
}

问题B:特殊排序
问题描述:
输入一系列整数,将其中最大的数挑出,并将剩下的数进行排序。

  • 输入
输入第一行包括1个整数N,1<=N<=1000,代表输入数据的个数。
接下来的一行有N个整数。
  • 输出
可能有多组测试数据,对于每组数据,
第一行输出一个整数,代表N个整数中的最大值,并将此值从数组中去除,将剩下的数进行排序。
第二行将排序的结果输出。
  • 样例输入
5
5 3 2 4 1
  • 样例输出
5
1 2 3 4

这题和A差不多,先把数组最后一位输出了,然后输出1到n-1位元素即可,需要注意如果只有一个元素,第二行输出-1

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int n;
	int a[1010];
	int i;
	while (scanf("%d", &n) != EOF)
	{
		for (i = 0; i < n; i++)
		{
			scanf("%d", &a[i]);	
		}
		sort(a, a + n);
		printf("%d\n", a[n-1]);
		if (n > 1)
		{
			for (i = 0; i < n - 1; i++)
			{
				printf("%d ", a[i]);
			}
		}
		if (n == 1)
			printf("-1");		
		printf("\n");
		memset(a, 0, sizeof(a));
	}	
	return 0;
}

问题C:EXECL排序
问题描述:
Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。

  • 输入
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (N<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号。以下有N行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。
  • 输出
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
  • 样例输入
4 1
000001 Zhao 75
000004 Qian 88
000003 Li 64
000002 Sun 90
4 2
000005 Zhao 95
000011 Zhao 75
000007 Qian 68
000006 Sun 85
4 3
000002 Qian 88
000015 Li 95
000012 Zhao 70
000009 Sun 95
0 3
  • 样例输出
Case 1:
000001 Zhao 75
000002 Sun 90
000003 Li 64
000004 Qian 88
Case 2:
000007 Qian 68
000006 Sun 85
000005 Zhao 95
000011 Zhao 75
Case 3:
000012 Zhao 70
000002 Qian 88
000009 Sun 95
000015 Li 95

注意sort的cmp函数在比较字符串时是用strcmp函数的返回值来看的,不然会报错invalid comparater,即无效的比较符。

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct student {
	char id[8];
	char name[10];
	int score;
}stu[100010];
//下面按照学号递增排序
bool cmp1(student a, student b) {
	return strcmp(a.id, b.id) < 0;
}
//下面按照姓名非递减排序,若姓名相同学号递增
bool cmp2(student a, student b) {
	if (strcmp(a.name, b.name) != 0)
		return strcmp(a.name, b.name) <= 0;
	else
		return strcmp(a.id, b.id) < 0;
}
//下面按照成绩非递减排序
bool cmp3(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,C;
	int i;
	int num=0;
	while (scanf("%d %d",&N,&C) != EOF)
	{
		if (N == 0)
			break;
		num++;
		for (i = 0; i < N; i++)
		{
			scanf("%s %s %d",&stu[i].id,&stu[i].name,&stu[i].score);
		}
		if (C == 1)
		{
			printf("Case %d:\n", num);
			sort(stu,stu+N,cmp1);
			for (i = 0; i < N; i++)
				printf("%s %s %d\n", stu[i].id, stu[i].name, stu[i].score);
		}
		else if (C == 2)
		{
			printf("Case %d:\n", num);
			sort(stu, stu + N, cmp2);
			for (i = 0; i < N; i++)
				printf("%s %s %d\n", stu[i].id, stu[i].name, stu[i].score);
		}
		else {
			printf("Case %d:\n",num);
			sort(stu, stu + N, cmp3);
			for (i = 0; i < N; i++)
				printf("%s %s %d\n", stu[i].id, stu[i].name, stu[i].score);
		}
	}	
	return 0;
}

问题D:字符串内排序
问题描述:输入一个字符串,长度小于等于200,然后将输出按字符顺序升序排序后的字符串。

  • 输入
测试数据有多组,输入字符串。
  • 输出
对于每组输入,输出处理后的结果。
  • 样例输入
tianqin
  • 样例输出
aiinnqt

这题注意输入得字符串中可能有空格,基础题sort函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	char str[210];
	int len;
	while (gets_s(str) != NULL)
	{
		len = strlen(str);
		sort(str,str+len);
		printf("%s",str);
		memset(str,'\0',sizeof(str));
	}	
	return 0;
}

问题E:Problem B
问题描述:请写一个程序,对于一个m行m列的(1<m<10)的方阵,求其每一行,每一列及主对角线元素之和,最后按照从大到小的顺序依次输出。

  • 输入
共一组数据,输入的第一行为一个正整数,表示m,接下来的m行,每行m个整数表示方阵元素。
  • 输出
从大到小排列的一行整数,每个整数后跟一个空格,最后换行。
  • 样例输入
4
15 8 -2 6
31 24 18 71
-3 -9 27 13
17 21 38 69
  • 样例输出
    159 145 144 135 81 60 44 32 28 27

```cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
bool cmp(int a, int b)
{
	return a >= b;
}
int main()
{
	int m;
	int i,j;
	int a[12][12];
	int b[25] = {0};
	int temp;
	while (scanf("%d", &m) != EOF)
	{
		temp = 2;
		//下面输入矩阵
		for (i = 1; i <= m; i++)
		{
			for (j = 1; j <= m; j++)
			{
				scanf("%d", &a[i][j]);
				//printf("!!!%d\n", a[i][j]);
				b[temp] += a[i][j];//计算一行的和
			}
			//getchar();
			temp++;
		}
	
		//下面计算一列的和与两条对角线的和b[0]b[1]
		for (j = 1; j <= m; j++)
		{
			for (i = 1; i <= m; i++)
			{
				b[temp] += a[i][j];
				if (i == j)
					b[0] += a[i][j];
				if(i+j-1==m)
					b[1] += a[i][j];
			}
			temp++;
		} 
		//下面排序输出
		sort(b, b + temp, cmp);
		for (i = 0; i < temp; i++)
			printf("%d ",b[i]);
		printf("\n");
		memset(b, 0,sizeof(b));
	}	
	return 0;
}

问题F:小白鼠排队
问题描述:N只小白鼠(1 <= N <= 100),每只鼠头上戴着一顶有颜色的帽子。现在称出每只白鼠的重量,要求按照白鼠重量从大到小的顺序输出它们头上帽子的颜色。帽子的颜色用“red”,“blue”等字符串来表示。不同的小白鼠可以戴相同颜色的帽子。白鼠的重量用整数表示。

  • 输入
多案例输入,每个案例的输入第一行为一个整数N,表示小白鼠的数目。
下面有N行,每行是一只白鼠的信息。第一个为不大于100的正整数,表示白鼠的重量,;第二个为字符串,表示白鼠的帽子颜色,字符串长度不超过10个字符。
注意:白鼠的重量各不相同。
  • 输出
每个案例按照白鼠的重量从大到小的顺序输出白鼠的帽子颜色。
  • 样例输入
1
79 omi
9
46 lcg
92 cru
37 ceq
54 vhr
17 wus
27 tnv
13 kyr
95 wld
34 qox
  • 样例输出
omi
wld
cru
vhr
lcg
ceq
qox
tnv
wus
kyr

思路是用sort对结构体进行排序,然后输出结构体中的颜色即可,略

问题G:中位数
问题描述:中位数定义:一组数据按从小到大的顺序依次排列,处在中间位置的一个数(或最中间两个数据的平均数).
给出一组无序整数,求出中位数,如果求最中间两个数的平均数,向下取整即可(不需要使用浮点数)

  • 输入
该程序包含多组测试数据,每一组测试数据的第一行为N,代表该组测试数据包含的数据个数,1<=N<=10000.
接着N行为N个数据的输入,N=0时结束输入
  • 输出
输出中位数,每一组测试数据输出一行
  • 样例输入
1
468
15
501
170
725
479
359
963
465
706
146
282
828
962
492
996
943
0
  • 样例输出
468
501

基础题,略

问题H:整数奇偶排序
问题描述:输入10个整数,彼此以空格分隔。重新排序以后输出(也按空格分隔),要求:
1.先输出其中的奇数,并按从大到小排列;
2.然后输出其中的偶数,并按从小到大排列。

  • 输入
任意排序的10个整数(0100),彼此以空格分隔。
  • 输出
可能有多组测试数据,对于每组数据,按照要求排序后输出,由空格分隔。
  • 样例输入
0 56 19 81 59 48 35 90 83 75 
17 86 71 51 30 1 9 36 14 16 
  • 样例输出
83 81 75 59 35 19 0 48 56 90
71 51 17 9 1 14 16 30 36 86

用两个数组分别存储奇数和偶数就可以了,略

问题I:排名
问题描述:今天的上机考试虽然有实时的Ranklist,但上面的排名只是根据完成的题数排序,没有考虑每题的分值,所以并不是最后的排名。给定录取分数线,请你写程序找出最后通过分数线的考生,并将他们的成绩按降序打印。

  • 输入
测试输入包含若干场考试的信息。每场考试信息的第1行给出考生人数N ( 0 < N < 1000 )、考题数M ( 0 < M < = 10 )、分数线(正整数)G;第2行排序给出第1题至第M题的正整数分值;以下N行,每行给出一名考生的准考证号(长度不超过20的字符串)、该生解决的题目总数m、以及这m道题的题号(题目号由1到M)。 
当读入的考生人数为0时,输入结束,该场考试不予处理。
  • 输出
对每场考试,首先在第1行输出不低于分数线的考生人数n,随后n行按分数从高到低输出上线考生的考号与分数,其间用1空格分隔。若有多名考生分数相同,则按他们考号的升序输出。
  • 样例输入
3 5 32
17 10 12 9 15
CS22003 5 1 2 3 4 5
CS22004 3 5 1 3
CS22002 2 1 5
0
  • 样例输出
3
CS22003 63
CS22004 44
CS22002 32

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct student {
	char id[30];
	int score;
}stu[1010];
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, M, G;
	int a[12];
	int i,j;
	int temp1,temp2;
	int num;
	while (scanf("%d %d %d", &N, &M, &G) != EOF)
	{
		if (N == 0)
			break;
		for (i = 1; i <= M; i++)//输入M题的分值
		{
			scanf("%d", &a[i]);
		}
		num = 0;
			//下面输入id以及计算成绩
		for (i = 1; i <=N; i++)
		{
			stu[i].score = 0;
			scanf("%s %d", &stu[i].id, &temp1);
			for (j = 0; j < temp1; j++)
			{
				scanf("%d",&temp2);
				stu[i].score += a[temp2];
			}
			if (stu[i].score >= G)
				num++;
		}
		//下面对成绩从大到小,对结构体排序
		sort(stu + 1, stu + N + 1, cmp);
		printf("%d\n", num);
		for (i = 1; i <= N; i++)
		{
			if (stu[i].score < G)
				break;
			else
				printf("%s %d\n",stu[i].id,stu[i].score);
		}
	 	}	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值