两种多关键字排序代码

#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;
}

 

上一篇:查看程序设计OJ通过码的方式


下一篇:C++读取文件