注:此文章是从回收站里拉回来的,懒得排版,所以没有缩进,凑活看吧
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;
}
运行结果:
nanjingsuzhou
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补充篇
#include<cstdio>
int main()
{
double a = 003.14159;
int b = 0032;
printf("%.4f %06d", a, b);
return 0;
}
#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;
}