【算法训练】排序

一、冒泡排序

#include<stdio.h>
int main(){
    int n;
    int buf[100];
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%d",&buf[i]);
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n-1-i;j++){
                if(buf[j]>buf[j+1]){
                    int t=buf[j];
                    buf[j]=buf[j+1];
                    buf[j+1]=t;
                }
            }
        }//冒泡排序
        for(int i=0;i<n;i++){
            printf("%d ",buf[i]);
        } 
        printf("\n");
    }
    return 0;
} 

第一,scanf函数是有返回值的 (尽管大多时候都会被人忽略),它将返回被输入函数成功赋值的变量个数。在 此例中,若成功完成输入并对n赋值,scanf函数的返回值即为1。
我们即是通过 该返回值来完成循环条件的判断的。第二,我们也要注意到,该例题面中明确了 输入数据会有多组,我们将要对每组输入都输出相应答案。并且,事先我们并不 知道将会有多少组数据被输入到程序中。
于是,我们可以使用该循环测试条件来 完成对输入是否结束的判断。过程如下:如仍有测试数据未被测试完,那么该组 测试的开头一行将如题面所说,为一个整数(n),其将会被scanf语句赋值给变 量n,那么scanf返回值为1,不等于EOF(-1),循环条件成立,程序进入循环体, 执行程序;
如果输入已经到达结尾(输入文件到达末尾或在命令台输入中输入 Ctrl+z),scanf函数无法再为变量n赋值,于是scanf函数返回EOF(end of file)。 至此,循环条件不成立,程序跳过循环体,执行return 0,使程序正常的结束.

二、利用c++库函数实现快速排序

利用库函数升序排列

#include<stdio.h>
#include<algorithm>
using namespace std;
int main(){
    int n;
    int buf[10000];
    while(scanf("%d",&n)==1){
        for(int i=0;i<n;i++){
            scanf("%d",&buf[i]);
        }
        sort(buf,buf+n);//使用该重载形式,表明要使用自己定义的排列规则
        for(int i=0;i<n;i++){
            printf("%d ",buf[i]);
        } 
        printf("\n");
    } 
    return 0;
} 

此例中,sort函数的两个参数代表待排序内存的起 始地址和结束地址(sort 函数还有另外的重载形式,在后文中会有所提及),在 此例中起始地址为buf,结束地址为buf + n。
该函数调用完成后,buf数组中的 数字就已经通过快速排序升序排列。我们只需对其输出即可。 
利用该库函数实现降序排列

#include<stdio.h>
#include<algorithm>
using namespace std;
bool cmp(int x,int y){
    return x>y;//定义排序规则 
} 
int main(){
    int n;
    int buf[100];
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%d",&buf[i]);
        }
        sort(buf,buf+n,cmp);//使用该重载形式,表明我们将要使用自己定义的排序规则进行排序
        for(int i=0;i<n;i++){
          printf("%d ",buf[i]);
       } 
       printf("\n");
    }
    return 0;
} 

如该代码所示,我们新定义了一个cmp函数,来实现对于新的排序规则的定义。
关于cmp函数的定义规则我们只需简单的记得,当cmp的返回值为true时, 即表示 cmp 函数的第一个参数将会排在第二个参数之前(即在我们定义的规则 中,cmp 表示第一个参数是否比第二个参数大,若是,则排在前面)。
为了实现 降序排列,我们只要判断两个参数的大小,当第一个参数比第二个参数大时返回 true。然后,只需要调用sort函数的另一种重载方式:sort(排序起始地址,排序
结束地址,比较函数),如代码所示,我们便完成了对我们给定的内存区间 的降序排列。 对于利用sort函数为其它基本类型(如double,char等)排序的方法也大同小异。### 三、例题
题目描述

有 N 个学生的数据,将学生数据按成绩高低排序,如果成绩相同则按姓名 字符的字母序排序,如果姓名的字母序也相同则按照学生的年龄排序,并输出N 个学生排序后的信息。 
输入:
测试数据有多组,每组输入第一行有一个整数 N(N<=1000),接下来的 N 行包括N个学生的数据。每个学生的数据包括姓名(长度不超过100的字符串)、 年龄(整形数)、成绩(小于等于100的正数)
输出:
将学生信息按成绩进行排序,成绩相同的则按姓名的字母序进行排序。然后 输出学生信息,按照如下格式:姓名 年龄 成绩 
样例输入:

abc 20 99 
bcd 19 97 
bed 20 97 
样例输出:
bcd 19 97 
bed 20 97 
abc 20 99 解法一 定义cmp函数

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct E{
    char name[101];
    int age;
    int sorce;
}buf[1000];
bool cmp(E a,E b){
    if(a.sorce !=b.sorce) return a.sorce<b.sorce;//分数不相同的,让分数低的在前面
    int tmp=strcmp(a.name,b.name);
    if(tmp!=0) return tmp<0;//若分数相同,按名字字典序小者在前
    else return a.age<b.age;//若前两者相同,则年龄小的在前
     
}
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%s%d%d",buf[i].name,&buf[i].age,&buf[i].sorce);
        }
        sort(buf,buf+n,cmp);//利用自己定义的规则进行排序
        for(int i=0;i<n;i++){
            printf("%s %d %d\n",buf[i].name,buf[i].age,buf[i].sorce); 
        } 
    }
    return 0;
} 

重载小于运算符

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct E{
    char name[101];
    int age;
    int score;
    bool operator < (const E &b) const{
        //利用c++运算符重载直接定义小于运算符
        if(score!= b.score) return score< b.score;
        int tmp=strcmp(name,b.name);
        if(tmp!=0) return tmp<0;
        else return age<b.age; 
    
    }
}buf[1000];
int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%s%d%d",buf[i].name,&buf[i].age,&buf[i].score);
        }
        sort(buf,buf+n);
        for(int i=0;i<n;i++){
            printf("%s %d %d\n",buf[i].name,buf[i].age,buf[i].score);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值