针对最近某天的世界各国新冠肺炎疫情数据,对累积确诊病例数排名靠前的100个国家(包括中国)的新增确诊,累积治愈和死亡病例数,治愈率和病死率分别进行排序,要求采用三种以上不同的排序方法来实现,并输出排序后的国家名和相应的病例数。
这里使用了6种不同的排序方法来进行排序,分别是:
1.折半插入排序2.希尔排序3.冒泡排序4.快速排序5.选择排序6.归并排序
其中数据需要和程序保存在同一个文件夹中,或者修改路径也成。
#include<iostream>
#include<vector>
#include<string>
#define N 100
using namespace std;
struct virus
{
int index;//作为国家的索引
int new_cases;
long int confirmed_cases;
long int recover_cases;
long int death_cases;
double recover_rate;
double death_rate;
};
//初始化
void read_from_file(vector<virus>&data,vector<string>&countries)
{
FILE *fp = fopen("covid_19.txt","r");
if(!fp)
{
printf("打开文件失败!\n");
}
int num;
string name;
for(int i = 0;i < N;i++)
{
fscanf(fp,"%s%d%ld%ld%ld",&countries[i][0],&data[i].new_cases,&data[i].confirmed_cases,&data[i].recover_cases,&data[i].death_cases);
fscanf(fp,"\n");
data[i].recover_rate= double(data[i].recover_cases)/double(data[i].confirmed_cases);
data[i].death_rate = double(data[i].death_cases)/double(data[i].confirmed_cases);
data[i].index = i;
// printf("国家=%s",countries[i].c_str());
// printf(",新增病例=%d",data[i].new_cases);
// printf(",确诊病例=%ld",data[i].confirmed_cases);
// printf(",治愈病例=%ld",data[i].recover_cases);
// printf(",死亡病例=%ld",data[i].death_cases);
// printf(",治愈率=%f",data[i].recover_rate);
// printf(",死亡率=%f\n",data[i].death_rate);
}
fclose(fp);
}
class Sort_array
{
public:
double varify(virus data,int way)
{
switch(way)
{
case 1:return data.new_cases;//int
case 2:return data.confirmed_cases;//long int
case 3:return data.recover_cases;//long int
case 4:return data.death_cases;//long int
case 5:return data.recover_rate;//double
case 6:return data.death_rate;//double
default:
return 0;
}
return 0;
}
//排序新增病例,采用冒泡排序
void Bubblesort(vector<virus>&data,int way)
{
int i,j;
virus tmp;
bool exchange;
for(i=0;i<N-1;i++)
{
exchange = false;
for(j=N-1;j>i;j--)//比较,找出关键词最小的元素
{
if(varify(data[j],way)>varify(data[j-1],way))
{
tmp = data[j];//new_cases[j]与new_cases[j-1]进行比较,将关键词最小的元素前移
data[j] = data[j-1];
data[j-1] = tmp;
exchange = true;
}
}
if(!exchange)//本趟没有发生交换,中途结束算法
{
return;
}
}
}
//排序确证病例,采用快速排序
void Quicksort(vector<virus>&data,int s, int t, int way)
{
int i = s, j = t;//设置两个指针初始时分别指向无序区中第一个和最后一个元素
virus tmp;
if (s < t)
{
tmp = data[s];//首先将data[s]移至tmp中作为基准
while(i != j)
{
while(j>i&&varify(data[j],way)<=varify(tmp,way))//令j自t向左扫描直至data[j].key<tmp.key
{
j--;
}
data[i] = data[j];//将data[j]移至i所指的位置上
while(i<j&&varify(data[i],way)>=varify(tmp,way))//i自i+1其向右扫描直至data[i].key>tmp.key
{
i++;
}
data[j] = data[i];//将data[i]移至j所指的位置上
}
//此时所有data[k](k=s,s+1,……,i-1)的关键字都小于tmp.key,而所有data[k](k=i+1,j+2,……,t)中的关键字都大于tmp
data[i] = tmp;//将tmp中的元素移至data[i]
Quicksort(data,s,i-1,way);//左区间递归排序
Quicksort(data,i+1,t,way);//右区间递归排序
}
}
//排序死亡率,采用折半插入排序
void Insertsort(vector<virus>&data,int way)
{
int i,j,low,high,mid;
virus tmp;
for(i = 1;i<N;i++)
{
tmp = data[i];
low = 0; high = i - 1;
while(low<=high)
{
mid = (low + high)/2;
if(varify(tmp,way)>varify(data[mid],way))
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
for(j = i - 1;j>=high+1;j--)
{
data[j+1] = data[j];
}
data[high+1] = tmp;
}
}
//排序死亡病例,采用希尔排序
void Shellsort(vector<virus>&data,int way)
{
int i,j,gap;
virus tmp;
gap = N/2;
while(gap>0)
{
for(i=gap;i<N;i++)
{
tmp = data[i];
j = i - gap;
while(j>=0&&varify(tmp,way)>varify(data[j],way))
{
data[j+gap] = data[j];
j = j - gap;
}
data[j+gap] = tmp;
}
gap = gap/2;
}
}
//排序治愈病例,采用选择排序
void Selectsort(vector<virus>&data, int way)
{
int i,j,k;
virus tmp;
for(i = 0;i < N-1;i++)
{
k = i;
for(j = i +1;j<N;j++)
{
if(varify(data[j],way)>varify(data[k],way))
k = j;
}
if(k!=i)
{
tmp = data[i];
data[i] = data[k];
data[k] = tmp;
}
}
}
void Merge(vector<virus>&data, int low, int mid, int high, int way)//归并排序
{
virus *R1;
int i = low, j = mid + 1, k = 0;
R1 = (virus*)malloc((high-low+1)*sizeof(virus));
while(i<=mid&&j<=high)
{
if(varify(data[i],way)>=varify(data[j],way))
{
R1[k] = data[i];
i++;k++;
}
else
{
R1[k] = data[j];
j++;k++;
}
}
while(i<=mid)
{
R1[k] = data[i];
i++;k++;
}
while(j<=high)
{
R1[k] = data[j];
j++;k++;
}
for(k=0,i=low;i<=high;k++,i++)
{
data[i] = R1[k];
}
free(R1);
}
void MergePass(vector<virus>&data, int length, int n,int way)
{
int i;
for(i = 0;i+2*length-1<n;i=i+2*length)
{
Merge(data,i,i+length-1,i+2*length-1,way);
}
if(i+length-1<n)
{
Merge(data,i,i+length-1,n-1,way);
}
}
void Mergesort(vector<virus>&data,int n,int way)
{
int length;
for(length=1;length<n;length=2*length)
{
MergePass(data,length,n,way);
}
}
};
//问题在于国家怎么办,总不能每次排序,都把国家也排一次序
int main()
{
vector<virus>data(N);
vector<string>countries(N);
read_from_file(data,countries);
//对上述包括治愈率和病死率进行排序,要求对三种以上不同的排序方法来实现,并输出排序后的国家名和相应的病例数。
int choose,way,print_way;
printf("请选择需要排序的部分:1.新增病例2.确诊病例3.治愈病例4.死亡病例5.治愈率6.死亡率\n");
scanf("%d",&choose);
printf("请选择要使用的排序方法:1.折半插入排序2.希尔排序3.冒泡排序4.快速排序5.选择排序6.归并排序\n");
scanf("%d",&way);
Sort_array sort_data;
switch (way)
{
case 1:sort_data.Insertsort(data,choose);break;
case 2:sort_data.Shellsort(data,choose);break;
case 3:sort_data.Bubblesort(data,choose);break;
case 4:sort_data.Quicksort(data,0,N-1,choose);break;
case 5:sort_data.Selectsort(data,choose);break;
case 6:sort_data.Mergesort(data,N,choose);break;
default:printf("没有找到所需方法\n");
}
printf("请选择正序输出或是反序输出:1.正序输出2.反序输出:");
scanf("%d",&print_way);
if(print_way==1)
{
printf("按正序排序:\n");
switch(choose)
{
case 1:
{
for(int i = 0;i<N;i++)
{
printf("%d.国家:%s,新增病例:%d\n",i+1,&countries[data[i].index][0],data[i].new_cases);
}
break;
}
case 2:
{
for(int i = 0;i<N;i++)
{
printf("%d.国家:%s,确诊病例:%ld\n",i+1,&countries[data[i].index][0],data[i].confirmed_cases);
}
break;
}
case 3:
{
for(int i = 0;i<N;i++)
{
printf("%d.国家:%s,治愈病例:%ld\n",i+1,&countries[data[i].index][0],data[i].recover_cases);
}
break;
}
case 4:
{
for(int i = 0;i<N;i++)
{
printf("%d,国家:%s,死亡病例:%ld\n",i+1,&countries[data[i].index][0],data[i].death_cases);
}
break;
}
case 5:
{
for(int i = 0;i<N;i++)
{
printf("%d.国家:%s,治愈率:%f\n",i+1,&countries[data[i].index][0],data[i].recover_rate);
}
break;
}
case 6:
{
for(int i = 0;i<N;i++)
{
printf("%d.国家:%s,死亡率:%f\n",i+1,&countries[data[i].index][0],data[i].death_rate);
}
break;
}
}
}
else if(print_way==2)
{
printf("按反序排序:\n");
switch(choose)
{
case 1:
{
for(int i = N-1;i>0;i--)
{
printf("%d.国家:%s,新增病例:%d\n",i+1,&countries[data[i].index][0],data[i].new_cases);
}
break;
}
case 2:
{
for(int i = N-1;i>=0;i--)
{
printf("%d.国家:%s,确诊病例:%ld\n",i+1,&countries[data[i].index][0],data[i].confirmed_cases);
}
break;
}
case 3:
{
for(int i = N-1;i>=0;i--)
{
printf("%d.国家:%s,治愈病例:%ld\n",i+1,&countries[data[i].index][0],data[i].recover_cases);
}
break;
}
case 4:
{
for(int i = N-1;i>=0;i--)
{
printf("%d,国家:%s,死亡病例:%ld\n",i+1,&countries[data[i].index][0],data[i].death_cases);
}
break;
}
case 5:
{
for(int i = N-1;i>=0;i--)
{
printf("%d.国家:%s,治愈率:%f\n",i+1,&countries[data[i].index][0],data[i].recover_rate);
}
break;
}
case 6:
{
for(int i = N-1;i>=0;i--)
{
printf("%d.国家:%s,死亡率:%f\n",i+1,&countries[data[i].index][0],data[i].death_rate);
}
break;
}
}
}
return 0;
}
实验结果:
我采集的某一天的数据为:
我的数据存储格式为:
国家 新增病例 确诊病例 治愈病例 死亡病例
比如:
美国 25450 2208400 903041 119132
而治愈率计算方法是治愈病例/确诊病例
死亡率计算方法类似死亡病例/确诊病例
排序过程比较顺利因为书上都有详细的对应的原理和代码,主要是在数据导入上时间画得比较长,查找并且整理数据花了挺长时间,数据处理完后排序就方便了。碰到的第一个问题是开始时我没有把这些数据包装成一个数据结构而是单个数组因为输出的时候要对应国家这样只能把数据的排序显示出来就修改成了一个把国家和要排序的所有数据一起包装成一个结构体;但是打印出来的国家总是为空,我也单独在一个新程序里实验了一下,原因好像是因为在结构体中字符串不能赋值,如果两个数据都是字符串类型,可以相互赋值,但是如果字符串是结构体中的一个元素如果赋值的话,就会丢失数据输出空白,我就想到解决办法,干脆给每个国家都对应一个编号,国家的顺序不改变,只是打印对应序号的国家,问题就解决了;后来碰到了一个问题,我一开始本来是使用一个数值比如新增病例这一项对应一个排序方法,后来我想改进为可以选择一项使用任意方法排序,可是题目里用到了三种数据类型int,long int和double,因此后面我增加了一个函数,调用这个函数可以返回需要排序的类型的数值。