排序、检索 2016.2.5

来源:互联网 发布:apache php nginx 编辑:程序博客网 时间:2024/06/03 17:59

1、HDU 1862 EXCEL排序(结构体排序练习)
题意:
对一个结构体以不同的标准进行排序。
解题思路:
看到题目中对结构体数组元素数目限制为小于1000000,我果断使用了系统排序函数qsort(),应为不论是冒泡排序还是选择排序,运算量过于庞大,必将会超时。题目中在以姓名和成绩排序时使用到了结构体二级排序,即如果首先排序对象相同时,以二级排序对象来确定数组元素的顺序。所以本题只需要确定三个不同的cmp()函数,以实现用不同的标准进行排序。另外看示范输出可知学号得以字符串形式存储。

Description
Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。

Input
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号。以下有 N
行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。

Output
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3
时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。

Sample Input

3 1
000007 James 85
000010 Amy 90
000001 Zoe 60
4 2
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 98
4 3
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 90
0 0

Sample Output

Case 1:
000001 Zoe 60
000007 James 85
000010 Amy 90
Case 2:
000010 Amy 90
000002 James 98
000007 James 85
000001 Zoe 60
Case 3:
000001 Zoe 60
000007 James 85
000002 James 90
000010 Amy 90

Source
浙大计算机研究生复试上机考试-2007年

Recommend
lcy

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;typedef struct _student {    char num[7];    char name[9];    int score;}_Student;_Student student[100001];int cmpnum(const void *a, const void *b){    _Student *x = (_Student*)a;    _Student *y = (_Student*)b;    return strcmp(x->num, y->num) > 0 ? 1 : -1;}int cmpname(const void *a, const void *b){    _Student *x = (_Student *)a;    _Student *y = (_Student *)b;    if(strcmp(x->name, y->name) != 0) {        return strcmp(x->name, y->name) > 0 ? 1 : -1;    }    return strcmp(x->num, y->num) > 0 ? 1 : -1;}int cmpscore(const void *a, const void *b){    _Student *x = (_Student *)a;    _Student *y = (_Student *)b;    if(x->score != y->score) {        return x->score - y->score > 0 ? 1 : -1;    }    return strcmp(x->num, y->num) > 0 ? 1 : -1;}int main(){    int N, C;    int i, j = 1;    while(scanf("%d%d", &N, &C) && N){        for(i=0; i<N; ++i){            scanf("%s%s%d", student[i].num, student[i].name, &student[i].score);        }        if(C == 1){            qsort(student, N, sizeof(student[0]), cmpnum);        }        else if(C == 2){            qsort(student, N, sizeof(student[0]), cmpname);        }        else if(C== 3){            qsort(student, N, sizeof(student[0]), cmpscore);        }        printf("Case %d:\n", j++);        for(i=0; i<N; ++i){            printf("%s %s %d\n", student[i].num, student[i].name, student[i].score);        }    }    return 0;}

2、UVa 10474 Where is the Marble?(大理石在哪?)

#include <iostream>#include <cstdlib>using namespace std;int cmp_num(const void *a, const void *b){    return (*(int *)a - *(int *)b);}int main(){    int N, Q;    int x[10010];    int y[10010];    int i, j;    int Case = 0;    while (cin>>N>>Q && (!(N==0&&Q==0))) {        ++Case;        cout<<"CASE# "<<Case<<":"<<endl;        for (i=0; i<N; ++i) {            cin>>x[i];        }        qsort(x, N, sizeof(int), cmp_num);        for (i=0; i<Q; ++i) {            cin>>y[i];            int flag = 0;            for (j=0; j<N; ++j) {                if (y[i] == x[j]) {                    flag = 1;                    cout<<y[i]<<" found at "<<j+1<<endl;                    break;                }            }            if (0 == flag) {                cout<<y[i]<<" not found"<<endl;            }        }    }    return 0;}

3、UVa 299 Train Swapping(列车交换)
题意:
先输入一个数L为需要排列的数的个数,接下来是L个无序的数字,任务是把其升序排列,计算需要交换几次。
解题思路:
这道题 实际就是冒泡 交换的模型是火车厢,只能相邻元素交换,也就是冒泡排序
只是在第二层循环内加一个计数的,就可以知道交换了几次。

#include <iostream>using namespace std;int main(){    int N;    int num[60];    int i, j;    while (cin>>N) {        while (N--) {            int count = 0;            int L;            cin>>L;            for (i=0; i<L; ++i) {                cin>>num[i];            }            int t;            for (i=0; i<L-1; ++i) {                for (j=i+1; j<L; ++j) {                    if (num[i] > num[j]) {                        t = num[i]; num[i] = num[j]; num[j] = t;                        ++count;                    }                }            }            cout<<"Optimal train swapping takes "<<count<<" swaps."<<endl;        }    }    return 0;}

4、UVa 755 487–3279
题意:
将每次所有输入的字符串转化为电话号码的标准形式,并输出出现次数大于1的电话号码和出现次数,注意在连续的输出之间输出一个空行
解题思路:
(1)、将每次所有输入字符串转化为整数,统计整数的出现次数,将出现次数大于1 的整数存进数组
(2)、对数组进行排序
(3)、根据电话号码的标准形式输出整数,然后输出此整数出现的次数

#include <iostream>#include <cstring>#include <map>#include <iomanip>#include <cstdio>using namespace std;int main(){    int n;    int num;    char directory[20];    int digital[25] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 0, 7, 7, 8, 8, 8, 9, 9, 9};    int len;    int i;//    while (cin>>n) {    while (scanf("%d", &n) != EOF) {        while (n--) {            scanf("%d", &num);//            cin>>num;            map<int, int>Map;            while (num--) {                scanf("%s", directory);//                cin>>directory;                len = strlen(directory);                int c = 0;                for (i=0; i<len; ++i) {                    if (directory[i]=='-') {                        continue;                    } else if (directory[i] <= '9') {                        c = c * 10 + directory[i] - '0';                    } else if (directory[i] <= 'Y') {                        c = c * 10 + digital[directory[i]-'A'];                    }                }                Map[c] += 1;            }            int flag = 0;            for (map<int, int>::iterator j=Map.begin(); j!=Map.end(); ++j) {                if (j->second > 1) {                    flag = 1;                    printf("%03d-%04d %d\n", (j->first)/10000, (j->first)%10000, j->second);//                    cout<<setfill('0')<<setw(3)<<(j->first)/10000;//                    cout<<"-";//                    cout<<setfill('0')<<setw(4)<<(j->first)%10000;//                    cout<<" ";//                    cout<<j->second<<endl;                }            }            if (0 == flag) {                printf("No duplicates.\n");//                cout<<"No duplicates."<<endl;            }            if (n > 0) {                cout<<endl;            }        }    }    return 0;}

5、UVa 400 Unix ls(Unix 的 ls 命令)
题意:
将输入的名字按照ASCII 值进行升序排序,然后以表格形式输出,要求是每行有60列,每个名字占的列数为最长名字长度加二,并且让列数达到最大。
解题思路:
1. 先用qsort()函数进行排序。
2. 求最大的列数,在求出对应的行数。
3. 用循环嵌套将结果输出。

#include <iostream>#include <cstdlib>#include <cstring>using namespace std;char filename[110][70];int cmp_string(const void *a, const void *b){    return strcmp((char *)a, (char *)b);}int main(){    int N;    int i, j, k, l;    int lie, hang;    char dashes[65] = "------------------------------------------------------------";    while (cin>>N) {        int len_max = 0;        for (i=0; i<N; ++i) {            cin>>filename[i];            if ((int)strlen(filename[i]) > len_max) {                len_max = strlen(filename[i]);            }        }        qsort(filename, N, sizeof(filename[0]), cmp_string);        lie = 60 / (len_max + 2);        if (lie == 0) {            lie = 1;        }        if (N%lie == 0) {            hang = N / lie;        } else {            hang = N / lie + 1;        }        cout<<dashes<<endl;        for (i=0; i<hang; ++i) {            for (j=i,k=0; (k<lie)&&(j<N); j+=hang,++k) {                cout<<filename[j];                for (l=0; l<(len_max + 2 - (int)strlen(filename[j])); ++l) {                    cout<<" ";                }            }            cout<<endl;        }    }    return 0;}
0 0