数据结构这一章主要讲的是关于排序的各种方法,由于不同应用对于时间复杂度与空间复杂度的要求不同,用的排序方法也不同,主要的排序方法有插入排序,交换排序,选择排序与归并排序,其中插入排序分为直接插入排序,间接插入排序与希尔排序,交换排序分为冒泡排序与快速排序,选择排序分为简单选择排序与堆排序,而归并排序则主要用于两个有序表的合成。以上的排序方法都属于是内部排序,而对于一些更大量的数据就要涉及到外部排序,下面是关于排序的应用习题。
给定公司N名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。
输入格式:
输入首先给出正整数N(≤105),即员工总人数;随后给出N个整数,即每个员工的工龄,范围在[0, 50]。
输出格式:
按工龄的递增顺序输出每个工龄的员工个数,格式为:“工龄:人数”。每项占一行。如果人数为0则不输出该项。
输入样例:
8
10 2 0 5 7 2 5 2
输出样例:
0:1
2:3
5:2
7:1
10:1
这道题属于排序应用中的简单题,只要用简单的冒泡排序加上输出的要求即可通过。
#include <iostream>
using namespace std;
int main()
{
int worktime[51]={0}; //定义一个数组(下标为工龄)来表示不同工龄的人数
int n; //定义参数
cin>>n; //输入人数
int a[n]; //定义一个数组存储输入的工龄
int i; //定义参数
for(i=0;i<n;i++) //循环输入
{
cin>>a[i]; //输入工龄
worktime[ a[i] ]++; //相应工龄的人数+1
}
for(i=0;i<=50;i++) //循环判断
{
if(worktime[i]!=0) //若该工龄人数不为0
{
cout<<i<<":"<<worktime[i]<<endl; //输出
}
}
return 0;
}
下面再来看一道比较难的题目。
计算机程序设计能力考试(Programming Ability Test,简称PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学的评价计算机程序设计人才,为企业选拔人才提供参考标准(网址http://www.patest.cn)。
每次考试会在若干个不同的考点同时举行,每个考点用局域网,产生本考点的成绩。考试结束后,各个考点的成绩将即刻汇总成一张总的排名表。
现在就请你写一个程序自动归并各个考点的成绩并生成总排名表。
输入格式:
输入的第一行给出一个正整数N(≤100),代表考点总数。随后给出N个考点的成绩,格式为:首先一行给出正整数K(≤300),代表该考点的考生总数;随后K行,每行给出1个考生的信息,包括考号(由13位整数字组成)和得分(为[0,100]区间内的整数),中间用空格分隔。
输出格式:
首先在第一行里输出考生总数。随后输出汇总的排名表,每个考生的信息占一行,顺序为:考号、最终排名、考点编号、在该考点的排名。其中考点按输入给出的顺序从1到N编号。考生的输出须按最终排名的非递减顺序输出,获得相同分数的考生应有相同名次,并按考号的递增顺序输出。
输入样例:
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
分析一下这道题目,题目要求求出考生总的排名以及在考点的排名,由于1个考点人数最多只有300人,用冒泡排序解决没什么大问题,但是在总的排序中如果使用冒泡排序,时间复杂度会大大提高,就会出现运行超时的情况,最后一个测试点会通不过,对于大的数据量我这里采用的是快速排序,相比于
O(n^2),O(nlog2n)明显就缩小了运行时间很多,下面分享一下我的代码(代码较长,可能需要改进)。
#include <iostream>
using namespace std;
typedef struct //定义考生结构体
{
int address; //考点
int score; //分数
int rank; //考点排名
int allrank; //总排名
string num; //学号
}student;
int partition(student a[], int left, int right) //快速排序一,用于总考生的分数排序
{
int i = left; //枢轴为最左侧
student temp; //定义一个结构体用于交换
for (int j = left; j < right; j++) //快速排序
{
if (a[j].score > a[left].score)
{
++i;
temp=a[i];a[i]=a[j];a[j]=temp;
}
}
temp=a[i];a[i]=a[left];a[left]=temp;
return i; //返回枢轴
}
int ex_partition(student a[], int left, int right) //快速排序二,用于总考生的相同分数的学号排序
{
int i = left; //枢轴为最左侧
student temp; //定义一个结构体用于交换
for (int j = left; j < right; j++)快速排序
{
if (a[j].num < a[left].num)
{
++i;
temp=a[i];a[i]=a[j];a[j]=temp;
}
}
temp=a[i];a[i]=a[left];a[left]=temp;
return i; //返回枢轴
}
void Qsort(student a[],int left,int right) //快速排序一的递归
{
if(left<right) //若排序划分未进行到底
{
int mid=partition(a,left,right); //获取枢轴
Qsort(a,left,mid); //左子表快速排序
Qsort(a,mid+1,right); //右子表快速排序
}
}
void ex_Qsort(student a[],int left,int right) //快速排序二的递归
{
if(left<right) //若排序划分未进行到底
{
int mid=ex_partition(a,left,right); //获取枢轴
ex_Qsort(a,left,mid); //左子表快速排序
ex_Qsort(a,mid+1,right); //右子表快速排序
}
}
int find(student a[],int s,int r) //快速排序二中寻找相同分数考生的函数
{
while(s!=r-1 && a[s].score==a[s+1].score)s++; //若与下一个考生分数相同,且不为最后一个(防止段错误),参数+1
return s+1; //返回值
}
int main()
{
int i,j,k,l,p,q; //定义参数
k=0; //参数置0
student a[30000]; //定义最大要求的结构体数组
student temp; //定义一个结构体用于交换
int n1,n2; //定义参数表示考点数与考点考生数
cin>>n1; //输入考点数
for(i=0;i<n1;i++)
{
cin>>n2; //输入考点考试数
l=k; //记录当前k值
for(j=0;j<n2;j++)
{
cin>>a[k].num>>a[k].score; //记录考试学号及分数
a[k].address=i+1; //记录考生考点
k++;
}
for(p=l;p<k;p++) //同一考点考生分数排序 (最大考生数为300,冒泡排序即可)
{
for(q=l;q<k;q++)
{
if(a[p].score>a[q].score)
{
temp=a[q];a[q]=a[p];a[p]=temp;
}
}
}
for(p=l;p<k;p++) //同一考点考生排名
{
if(p!=l && a[p].score==a[p-1].score)a[p].rank=a[p-1].rank; //若考生不为该考点第一个人,且分数与下一个人相同,则排名与上一个人相同
else a[p].rank=p-l+1; //分数不同,正常排名
}
}
int number=k; //记录总考生人数
Qsort(a,0,number); //总体按分数快速排序 (快速排序一)
k=0; //k置0
while(k<number) //若考生未排序完
{
l=k; //记录k值
k=find(a,k,number); //获取分数相同考生位置
ex_Qsort(a,l,k); //根据学号快速排序(快速排序二)
}
for(i=0;i<number;i++) //总排名
{
if(i!=0 && a[i].score==a[i-1].score)a[i].allrank=a[i-1].allrank; //若考生不为第一个人,且分数与下一个人相同,则排名与上一个人相同
else a[i].allrank=i+1; //分数不同,正常排名
}
//输出
cout<<number<<endl; //输出总人数
for(i=0;i<number;i++)
{
cout<<a[i].num<<" "<<a[i].allrank<<" "<<a[i].address<<" "<<a[i].rank<<endl; //按照格式输出学号,总排名,考点,考点排名
}
return 0;
}
以上,就是本人对于排序这一章的学习小结,如有错误,还请指出。