【写给李美琦的,其他人别看】

注:此文章是从回收站里拉回来的,懒得排版,所以没有缩进,凑活看吧




sort是C++标准模板库(Standard Template Library,即STL)中最常用的算法。其包含在头文件<algorithm>中,

我们只能对“数组”元素进行排序。在C++中,有且仅有如下两种调用方法(JAVA中略有不同):

sort(first, last)

sort(first, last, cmp)

其中first是数组的首地址,last是数组最后一个元素地址的后一个位置。也就是说,这是一个前闭后开区间[first, last)

而cmp是一个函数(不需要带括号和参数表)

对于c++的基本数据类型(int, char, double, long long之类)以及string,因为已经定义了2个元素之间的大小比较,故不需要cmp函数

而对于人为的自定义类型(如struct结构体),必须要人工定义其大小,或者采用cmp函数,我们才能进行sort排序

特别说明,sort默认是升序排序,因此如果需要降序排序,也需要人为定义cmp函数。


下面看这段代码:


#include<iostream>  
#include<algorithm>  
using namespace std;  
  
const int MAXN = 100 + 5;  
string a[MAXN];  
  
int main()  
{  
    a[0] = "nanjing";  
    a[1] = "suzhou";  
    a[2] = "shanghai";  
    a[3] = "beijing";  
    for(int i = 0; i < 4; i++) cout << a[i] << endl;  
    cout << endl;  
    sort(a, a + 4);  
    for(int i = 0; i < 4; i++) cout << a[i] << endl;  
    return 0;  
}  

运行结果:

nanjing
suzhou
shanghai
beijing


beijing
nanjing
shanghai
suzhou

string是c++中的对象,其源码是封装好的一个class类,已经定义好了大小(字典序)

因此我们直接排序即可得到这4个字符串按字典序升序排列的结果。


下面我们不采用字典序,而采用另外排序方法——首先根据字符串的长度降序来排序。长度相同的情况,再按字典序升序排列(套用这个格式即可,小于返回真,否则返回假)

bool cmp(string a, string b)
{
if(a.length() != b.length()) return a.length() > b.length();
else return a < b;
}

 调用sort(a, a + 4, cmp)运行结果:

shanghai
beijing
nanjing
suzhou


那么如果我们不去使用cmp函数呢?这里介绍第二种常用的方法——c++中的操作符重载。只要重载了小于号,即可只需2个参数调用sort函数。读者记住这种格式即可

示例:平面直角坐标系中,所有的点按距离原点的欧拉距离从大到小排列。相同距离再按x升序排列。相同的x再按y升序排列



#include<iostream>  
#include<algorithm>  
using namespace std;  
  
const int MAXN = 100 + 5;  
struct Node  
{  
    int x;  
    int y;  
    Node(int a = 0, int b = 0){x = a; y = b;}  
}node[MAXN];  
  
bool operator < (Node a, Node b)  
{  
    if(a.x * a.x + a.y * a.y != b.x * b.x + b.y * b.y)  
        return a.x * a.x + a.y * a.y > b.x * b.x + b.y * b.y;  
    else if(a.x != b.x)  
            return a.x < b.x;  
        else  
            return a.y < b.y;  
}  
  
int main()  
{  
    node[0] = Node(1, 1);  
    node[1] = Node(2, 3);  
    node[2] = Node(-2, 3);  
    node[3] = Node(2, -3);  
    sort(node, node + 4);  
    for(int i = 0; i < 4; i++)  
        cout << "(" << node[i].x << ", " << node[i].y << ")" << endl;  
    return 0;  
}  

运行结果:

(-2, 3)

(2, -3)

(2, 3)

(1, 1)

记住operator < 的格式即可。

其中Node(int a = 0, int b = 0){} 是c++里构造函数的用法

练习:PAT甲级1109

https://www.patest.cn/contests/pat-a-practise/1109

(自行注册账号并AC)

提示:算法竞赛必须避免使用cin、string,尤其是数据规模破千的题目

因此,可以直接使用char数组来替代string,同时加入头文件<cstring>

但字符串二维数组是无法用来做sort排序的,但是可以通过结构体里放一维数组,再给结构体数组排序来实现!

函数strlen(a)获取char数组a从a[0]到第一个'\0'之前的长度(不包括\0,比如char a[]={'a','\0','b','\0'}调用strlen(a)返回1)

函数strcmp(a, b)比较字符串a与b,如果相同返回0,如果前者字典序更小返回负数,否则返回正序(因此不能用来做sort的cmp函数)

函数memset(a, k, sizeof(a))用来给数组a全体赋值,其中常数k只能是0或者-1,不能是其他数字(因为是对字节操作不是对单个元素操作,这点可以从第三个参数看出),一般用来做多组用例下的数组的清零操作

函数memcpy(a, b, sizeof(b))用来将b数组的sizeof(b)个字节整体赋值给数组a

下面给出一个字符数组指针排序的示例,每个字符串最多输入19个字符:(竞赛一般不这么写,都是避免指针,在结构体内写一维数组然后对结构体排序)

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
using namespace std;  
char *a[200];  
bool cmp(char *s1, char *s2)  
{  
    int l1 = strlen(s1);  
    int l2 = strlen(s2);  
    int len = l1 < l2 ? l1 : l2;  
    for(int i = 0; i < len; i++)  
    {  
        if(s1[i] != s2[i]) return s1[i] < s2[i];  
    }  
    return l1 < l2;  
}  
  
int main()  
{  
    int n = 5;  
    for(int i = 0; i < n; i++)  
    {//必须先内存,否则会产生空指针异常  
        a[i] = (char*)malloc(20*sizeof(char));  
        scanf("%s", a[i]);  
    }  
    sort(a, a + n, cmp);  
    for(int i = 0; i < n; i++) printf("%s\n", a[i]);  
    return 0;  
}  

2017.04.11 sort补充篇


练习:PAT甲级1075
https://www.patest.cn/contests/pat-a-practise/1075
提示:不论是cin还是scanf,当我们输入int型时,都是忽略前缀0,比如00032依旧是读入的32,而输出时如果想保证有前缀0,必须用printf套格式
举例:.4f  默认四舍五入  double型scanf必须用%lf,输出必须用%f(不带l)

#include<cstdio>  
int main()  
{  
    double a = 003.14159;  
    int b = 0032;  
    printf("%.4f %06d", a, b);  
    return 0;  
}  
结果:
3.1416 000032




下面进一步介绍另外一种结构体内的操作符重载
这种模式的操作符重载格式请读者牢记,将<写到结构体内的效率至少是写在外面的3倍以上,以后所有的结构体排序均写成这样
以昨天的示例为例:平面直角坐标系中,所有的点按距离原点的欧拉距离从大到小排列。相同距离再按x升序排列。相同的x再按y升序排列



#include<iostream>  
#include<algorithm>  
using namespace std;  
  
const int MAXN = 100 + 5;  
struct Node  
{  
    int x;  
    int y;  
    Node(int a = 0, int b = 0){x = a; y = b;}  
    bool operator < (const Node& b) const  
    {  
        if(x * x + y * y != b.x * b.x + b.y * b.y)  
            return x * x + y * y > b.x * b.x + b.y * b.y;  
        else if(x != b.x)  
                return x < b.x;  
            else  
                return y < b.y;  
    }  
}node[MAXN];  
  
  
int main()  
{  
    node[0] = Node(1, 1);  
    node[1] = Node(2, 3);  
    node[2] = Node(-2, 3);  
    node[3] = Node(2, -3);  
    sort(node, node + 4);  
    for(int i = 0; i < 4; i++)  
        cout << "(" << node[i].x << ", " << node[i].y << ")" << endl;  
    return 0;  
}  


练习:南邮网赛G题  排序+贪心推公式综合题
http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=2184
(请自行用自己的账号登录并AC)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值