#include<iostream>
#include<iomanip>
#include<ctime>
#include<fstream>
#include<string>
#define radix 10
using namespace std;
clock_t start,stop;
//学生的结构体
typedef struct SNode{
string name;
int ID; //学号
int key[4]={0}; //成绩
struct SNode *next; //指针域
}SNode,*Student;
void StudentGrade(int n); //生成学生成绩信息文件new.txt,n为文件读取数据的组数
Student CreatStudent_old(Student &L,int num); //读取old.txt,尾插法建立学生成绩单链表L,num为总人数
Student CreatStudent_new(Student &L,int num); //读取new.txt,尾插法建立学生成绩单链表L,num为总人数
Student BubbleSort(Student &L,int order[]); //MSD冒泡排序,L为学生成绩链表,order[]为用户输入的次关键字顺序
Student RadixSort(Student &L,int order[]); //LSD基数排序,L为学生成绩链表,order[]为次关键字顺序
void Print(Student &L); //在屏幕上显示
void choose(Student &L); //选择功能
void Menu(); //菜单
int main(){
ofstream fout;
fout.open("C:\\Out.txt",ios::app);
if(!fout){
cout<<"无法打开文件!!!"<<endl;
}
int a;
do{
Menu(); //调用菜单
cout<<" 输入0结束,输入其他则可重新生成成绩再进行排序";
cin>>a;
fout<<" 输入0结束,输入其他则可重新生成成绩再进行排序"<<a;
}while(a!=0) ; //a等于0停止循环
return 0;
}
//菜单
void Menu(){
ofstream fout;
fout.open("C:\\Out.txt",ios::app);
if(!fout){
cout<<"无法打开文件!!!"<<endl;
}
cout<<endl;
cout<<endl;
cout<<" --------------------------------------------------"<<endl;
cout<<" |------------------学生成绩排序------------------|"<<endl;
cout<<" | |"<<endl;
cout<<" | 本程序可以按关键字的优先关系排序对成绩排序。 |"<<endl;
cout<<" | |"<<endl;
cout<<" | 学生成绩有两种方式产生 |"<<endl;
cout<<" | 输入1:从old.txt文件中读取 |"<<endl;
cout<<" | 输入2:随机产生数据并导入new.txt文件中 |"<<endl;
cout<<" --------------------------------------------------"<<endl;
cout<<endl;
//输出到文件
fout<<endl;
fout<<endl;
fout<<" --------------------------------------------------"<<endl;
fout<<" ------------------学生成绩排序------------------"<<endl;
fout<<" "<<endl;
fout<<" 本程序可以按关键字的优先关系排序对成绩排序。 "<<endl;
fout<<" "<<endl;
fout<<" 学生成绩有两种方式产生 "<<endl;
fout<<" 输入1:从old.txt文件中读取 "<<endl;
fout<<" 输入2:随机产生数据并导入new.txt文件中 "<<endl;
fout<<" --------------------------------------------------"<<endl;
fout<<endl;
Student L;
int a;
cout<<" 选择产生成绩的方式:";
cin>>a;
cout<<endl;
fout<<" 选择产生成绩的方式:"<<a<<endl;
switch (a) {
case 1:
int n;
cout<<" 从old.txt文件中读取多少组数据:";
cin>>n;
fout<<" 从old.txt文件中读取多少组数据:"<<n<<endl;
CreatStudent_old(L,n); //调用函数创建学生成绩单链表
break;
case 2:
int m;
cout<<" 需要随机产生多少组数据:";
cin>>m;
fout<<" 需要随机产生多少组数据:"<<m<<endl;
StudentGrade(m);
CreatStudent_new(L,m); //调用函数创建学生成绩单链表
break;
}
Print(L); //调用打印函数将生成的学生成绩信息打印在屏幕上
int b;
do{
cout<<" --------------------------------------------------"<<endl;
cout<<" | 请选择: |"<<endl;
cout<<" | 1.MSD策略对数据进行冒泡法排序 |"<<endl;
cout<<" | 2.LSD策略对数据进行基数排序 |"<<endl;
cout<<" --------------------------------------------------"<<endl;
fout<<" --------------------------------------------------"<<endl;
fout<<" 请选择: "<<endl;
fout<<" 1.MSD策略对数据进行冒泡法排序 "<<endl;
fout<<" 2.LSD策略对数据进行基数排序 "<<endl;
fout<<" --------------------------------------------------"<<endl;
choose(L); //调用选择函数,选择排序方式和排序次序
cout<<" 输入0结束,输入其他数则继续进行此成绩的排序";
cin>>b;
cout<<endl;
fout<<" 输入0结束,输入其他数则继续进行此成绩的排序"<<b<<endl;
}while(b!=0);
}
//生成学生成绩信息文件new.txt,n为需要随机生成的数据组数
void StudentGrade(int n){
ofstream fout;
fout.open("C:\\new.txt",ios::out);
if(!fout){
cout<<"无法打开文件!!!"<<endl;
}
string name; //姓名
int id; //学号
int score[4]; //分数
//随机产生数据并写入new中
string studentname[10]={"a","b","c","d","e","f","g","h","i","j"};
srand(time(0));
for(int a=1;a<=n;a++){
name=studentname[rand()%10] + studentname[rand()%10] + studentname[rand()%10];//对字进行随机组合生成姓名
fout<<name<<" ";
id=a;
fout<<id<<" ";
for(int c=0;c<=3;c++){ //初始化成绩
score[c]=0;
}
for(int b=0;b<3;b++){
score[b]=rand()%101; //随机产生成绩
fout<<score[b]<<" ";
score[3]=score[3]+score[b]; //总分
}
fout<<score[3]<<endl;
}
fout.close();
}
//读取old.txt,尾插法建立学生成绩单链表L,num为人数
Student CreatStudent_old(Student &L,int num){
ifstream fin;
fin.open("C:\\old.txt",ios::in);
if(!fin){
cout<<"无法打开文件!!!"<<endl;
}
Student p,r;
L=new SNode;
L->next=NULL; //创建带头结点的链表L
r=L; //尾指针指向头结点
for(int i=1;i<=num;i++){
p=new SNode; //生成新结点
fin>>p->name; //读取姓名
fin>>p->ID; //读取学号
for(int j=0;j<=3;j++){
fin>>p->key[j];
}
p->next=NULL;
r->next=p; //将新结点p插入尾结点r之后
r=p; //r指向新的尾结点p
}
return L;
}
//读取new.txt里的数据,尾插法建立学生成绩单链表L,num为人数
Student CreatStudent_new(Student &L,int num){
ifstream fin;
fin.open("C:\\new.txt",ios::in);
if(!fin){
cout<<"无法打开文件!!!"<<endl;
}
Student p,r;
L=new SNode;
L->next=NULL; //创建带头结点的链表L
r=L; //尾指针指向头结点
for(int i=1;i<=num;i++){
p=new SNode; //生成新结点
fin>>p->name; //读取姓名
fin>>p->ID; //读取学号
for(int j=0;j<=3;j++){
fin>>p->key[j];
}
p->next=NULL;
r->next=p; //将新结点p插入尾结点r之后
r=p; //r指向新的尾结点p
}
return L;
}
//选择功能
void choose(Student &L){
ofstream fout;
fout.open("C:\\Out.txt",ios::app);
if(!fout){
cout<<"无法打开文件!!!"<<endl;
}
double time; //排序时间
cout<<" ";
fout<<" ";
int order[4];
int a;
cin>>a;
fout<<a<<endl;
cout<<" --------------------------------------------------"<<endl;
fout<<" --------------------------------------------------"<<endl;
switch (a) {
case 1:
cout<<" 输入次关键字比较顺序,0为语文,1为数学,2为英语,3为总分,总分默认第一个"<<endl;
cout<<endl;
fout<<" 输入次关键字比较顺序,0为语文,1为数学,2为英语,3为总分,总分默认第一个"<<endl;
fout<<endl;
for(int i=0;i<=3;i++){
cout<<" 第"<<i+1<<"个次序";
cin>>order[i];
cout<<endl;
fout<<" 第"<<i+1<<"个次序";
fout<<order[i]<<endl;
}
start=clock();
BubbleSort(L,order); //调用冒泡排序
stop=clock();
time=(double)(stop-start)/CLK_TCK;
Print(L); //打印结果
cout<<" 排序所用时间:"<<time<<endl;;
fout<<" 排序所用时间:"<<time<<endl;
break;
case 2:
cout<<" 输入次关键字比较顺序,0为语文,1为数学,2为英语,3为总分,总分默认第一个"<<endl;
cout<<endl;
fout<<" 输入次关键字比较顺序,0为语文,1为数学,2为英语,3为总分,总分默认第一个"<<endl;
fout<<endl;
for(int i=0;i<=3;i++){
cout<<" 第"<<i+1<<"个次序";
cin>>order[i];
cout<<endl;
fout<<" 第"<<i+1<<"个次序";
fout<<order[i]<<endl;
}
start=clock();
RadixSort(L,order); //调用基数排序
stop=clock();
time=(double)(stop-start)/CLK_TCK;
Print(L);
cout<<" 排序所用时间:"<<time<<endl;
fout<<" 排序所用时间:"<<time<<endl;
break;
default:
cout<<" 选择不存在,请输入1或者2"<<endl;
fout<<" 选择不存在,请输入1或者2"<<endl;
break;
}
}
//MSD冒泡排序,L为学生成绩链表,order[]为用户输入的次关键字顺序
Student BubbleSort(Student &L,int order[]){
int flag=1; //标记,判断该趟排序是否发生交换
Student p,q,t;
while(flag==1){
t=L;
p=L->next;
q=p->next;
flag=0;
while(q){
int k1=order[0];
if(p->key[k1]<q->key[k1]){ //交换数据域,指针域不变
flag=1; //发生交换,flag变成1
p->next=q->next;
t->next=q;
q->next=p;
q=p->next;
}
else if(p->key[k1]==q->key[k1]){ //总分相等,比较第二次序
int k2=order[1];
if(p->key[k2]<q->key[k2]){
flag=1;
p->next=q->next;
t->next=q;
q->next=p;
q=p->next;
}
else if(p->key[k2]==q->key[k2]){ //第二次序相等,比较第三次序
int k3=order[2];
if(p->key[k3]<q->key[k3]){
flag=1;
p->next=q->next;
t->next=q;
q->next=p;
q=p->next;
}
if(p->key[k3]==q->key[k3]){ //第三次序相等,比较第四次序
int k4=order[3];
if(p->key[k4]<q->key[k4]){
flag=1;
p->next=q->next;
t->next=q;
q->next=p;
q=p->next;
}
else {
p=p->next;
q=q->next;
}
}//if(k2)
else {
p=p->next;
q=q->next;
}
}//if(k1)
else {
p=p->next;
q=q->next;
}
}//if(3)
else {
p=p->next;
q=q->next;
}
t=t->next;
}//while
}//while
return L;
}
//LSD基数排序,L为学生成绩链表,order[]为次关键字顺序
Student RadixSort(Student &L,int order[]){
Student front[radix],end[radix],p,t;
int m,k;
for(int n=3;n>=0;n--){
k=order[n];
for(int d=1;d<=3;d++){ //位数
for(int i=0;i<radix;i++){ //初始化各链队首尾指针
front[i]=end[i]=NULL;
}
p=L->next;
while(p){
if(d==1){
m=p->key[k]%10; //第一趟取个位分配
}
else if(d==2){
m=(p->key[k]%100)/10; //第二趟分配取十位
}
else{
m=p->key[k]/100; //第三趟取百位分配
}
if(front[m]==NULL){ //采用尾插法建立单链表
front[m]=p;
end[m]=p;
}
else{
end[m]->next=p;
end[m]=p;
}
p=p->next;
}//while
L->next=NULL;
for(int j=radix-1;j>=0;j--){ //对每一个链队从大到小进行收集
if(front[j]){
if(L->next==NULL){
L->next=front[j]; //L指向链队头
t=end[j]; //t指向队尾
}
else{
t->next=front[j]; //t->next指向下一个链队头
t=end[j];
}
}
t->next=NULL; //最后一个结点指向空
}//for
}
}
return L;
}
//在屏幕上显示
void Print(Student &L){
ofstream fout;
fout.open("C:\\Out.txt",ios::app);
if(!fout){
cout<<"无法打开文件!!!"<<endl;
}
cout<<" --------------------------------------------------"<<endl;
cout<<setw(8)<<"姓名"<<setw(8)<<"学号"<<setw(8)<<"语文"<<setw(8)<<"数学"<<setw(8)<<"英语"<<setw(8)<<"总分"<<endl;
fout<<" --------------------------------------------------"<<endl;
fout<<setw(8)<<"姓名"<<setw(8)<<"学号"<<setw(8)<<"语文"<<setw(8)<<"数学"<<setw(8)<<"英语"<<setw(8)<<"总分"<<endl;
Student p;
p=L->next;
while(p){
cout<<setw(8)<<p->name;
cout<<setw(8)<<p->ID;
fout<<setw(8)<<p->name;
fout<<setw(8)<<p->ID;
for(int i=0;i<4;i++){ //依次输出4个数据
cout<<setw(8)<<p->key[i];
fout<<setw(8)<<p->key[i];
}
cout<<endl;
fout<<endl;
p=p->next;
}
cout<<endl;
fout<<endl;
}