最近有点浮躁,无心练题,便捣鼓了一阵子的C++。接触了一点点的重载和模板后,心血来潮想写一点牛逼点的东西。因为平时打编程比赛要排序的地方都是直接用的C++中自带的sort排序函数,就想自己也写一个跟它功能差不多的sort函数(事实上写完后差远了)。折腾了两个小时,总算是写出了一个差强人意的代码。
C++算法库里的sort函数功能极其强大,据我所知它可以根据数据量实时选用不同的排序方式。很显然我这种蒟蒻是不会这种方式的。所以我的sort函数一整个就是一个非递归的归并排序。等以后更强大了再试着把它弄成更高级的函数吧~
按照惯例,先贴代码,再简要解释部分地方的代码实现。
#ifndef SORT_H
#define SORT_H
#include <iostream>
template<typename T, typename U>
void sort(T* begin, T* end, U op)
{
unsigned int N = end - begin;
T* Tmp = new T[N];
for (unsigned int l = 1; l < N; l *= 2) {
for (unsigned int i = 0; i + l - 1 < N; i += 2 * l) {
int s = i, m = i + l - 1, e = N - 1 > i + 2 * l - 1 ? i + 2 * l - 1 : N - 1, pb = 0;
int p1 = s, p2 = m + 1;
while (p1 <= m && p2 <=e) {
if (op(begin[p1], begin[p2]))
Tmp[pb++] = begin[p1++];
else
Tmp[pb++] = begin[p2++];
}
while (p1 <= m) Tmp[pb++] = begin[p1++];
while (p2 <= e) Tmp[pb++] = begin[p2++];
for (int i = 0; i < e - s + 1; ++ i) {
begin[s + i] = Tmp[i];
}
}
}
delete []Tmp;
}
template<typename T>
void sort(T* begin, T* end)
{
sort(begin, end, [](T a, T b){return a < b;});
}
#endif
为了证明我写的函数的可用性,还特意用它写了一遍洛谷的排序的板题:
最大的数据点38ms,还算不错,之前用C++库里的sort写的好像也就是36ms,差不多啦。
函数使用方式
由于我的函数中临时新开了一个数组,而这个数组类型由模板T决定,这导致了我不能把T直接定为指针类型,只能定成T类型(因为T = new T[len]中的T必须是非指针型的),这也就造成了我的sort的形参只能传地址而不能传迭代器(例如vector中的iterator)。所以目前它只能给普通的数组、结构体数组和类对象数组排序,后续我将寻找解决方案,并更新代码。
·函数各参数
该函数该传入的参数为某一数组待排序列的最左端地址及最右端地址右移一位(与C++sort函数的左闭右开性质相同)。第三个参数为可选参数,用户可自行定义排序逻辑,具体方法请往下看。
·对数组进行排序
- 以下默认是从小到大排序:
int a[] = {7, 5, 4, 6, 8, 9}; //数组长度是6
sort(a, a + 6); //遵循左闭右开原则
- 实现从大到小排序,有四种方法:
int a[] = {7, 5, 4, 6, 8, 9}; //数组长度是6
sort(a, a + 6, greater<int>() ); //仿函数,C++自带
bool cmp(int a, int b) {
return a > b;
}
int main()
{
int a[] = {7, 5, 4, 6, 8, 9}; //数组长度是6
sort(a, a + 6, cmp); //自定义比较函数
for (int i = 0; i < 6; i ++)
cout << a[i] << ' ';
return 0;
}
int a[] = {7, 5, 4, 6, 8, 9}; //数组长度是6
sort(a, a + 6, [](int a, int b){ return a > b;}); //利用C++的lambda函数
class cmp {
public:
bool operator() (int &a, int &b) const {
return a > b;
}
};
int main()
{
int a[] = {7, 5, 4, 6, 8, 9}; //数组长度是6
sort(a, a + 6, cmp() ); //利用类的仿函数
return 0;
}
·对结构体数组和对象数组排序
在C++里,结构体就相当于成员权限均为public的类。所以,接下来的举例我均用结构体来写。
结构体由于不能直接比较大小,所以不能直接排序。用户在给结构体排序的时候,需要自行做一些处理。
假设我们现在有一个这样的结构体数组:
假设我们的排序原则是num1小的排在前,num1相同的num2小的排在前。那么,我们可以用三种方法进行排序:
- 对结构体进行符号重载,注意要重载
<
号
struct node {
int num1;
int num2;
bool operator< (node &a) const {
if(num1 == a.num1)
return num2 < a.num2;
return num1 < a.num1;
}
}a[1000];
int main()
{
sort(a, a + 1000);
return 0;
}
- 自定义比较函数
struct node {
int num1;
int num2;
}a[1000];
bool cmp(node &a, node &b) {
if(a.num1 == b.num1)
return a.num1 < b.num1;
return a.num2 < b.num2;
}
int main()
{
sort(a, a + 1000,cmp);
return 0;
}
- lambda隐匿函数
struct node {
int num1;
int num2;
}a[1000];
int main()
{
sort(a, a + 1000,[](node &a, node &b) {
if(a.num1 == b.num1)
return a.num2 < b.num2;
return a.num1 < b.num1; } );
return 0;
}
- 仿函数
struct node {
int num1;
int num2;
}a[1000];
struct cmp {
bool operator()(node &a, node &b) const {
if(a.num1 == b.num1)
return a.num2 < b.num2;
return a.num1 < b.num1;
}
};
int main()
{
sort(a, a + 1000, cmp() );
return 0;
}
功能大概就是这些。日后我会慢慢将它变得更加完善。