stl sort和qsort的使用
好不容易使用了下stl的qsort函数,顺便和sort函数一起总结下:
很多时候我们都需要用到排序。
例如:
1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 6 int a[5] = {2, 1, 3, 5, 6};//对这个数组排序 7 int main() 8 { 9 sort(a, a + 5); 10 for (int i = 0; i < 5; i++) 11 cout<<a[i]<<endl; 12 return 0; 13 }
可以看到,sort默认是从小到达排序的,那如何自定义排序呢。
先看看sort的函数声明:
template <class RandomAccessIterator> void sort (RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class Compare> void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
sort函数将[first, last]区间按升序进行排序,排序是使用值类型的<运算符进行比较。第一个版本使用<来确定顺序,也就是从大到小,
第二个版本则使用自定义的比较对象或比较函数。
现在要对a[5] = {2, 1, 3, 5, 6};进行升序。
#include <iostream> #include <algorithm> using namespace std; int a[5] = {2, 1, 3, 5, 6}; int b[5] = {2, 1, 3, 5, 6}; bool cmp(const int a, const int b) { return a > b; } class cmpClass { public: bool operator () (const int a, const int b) { return a > b; } }; struct cmpStruct/**< 使用类似cmpClass */ { bool operator () (const int a, const int b)/**< 自定义比较对象需要重载()才行 */ { return a > b; } }; int main() { sort(a, a + 5, cmp);/**< 使用自定义函数 */ cout<<"a[]:"; for (int i = 0; i < 5; i++) cout<<' '<<a[i]; cout<<endl; cmpClass a;/**< 先声明个对象 */ sort(b, b + 5, a);/**< 使用比较对象 */ cout<<"b[]:"; for (int i = 0; i < 5; i++) cout<<' '<<b[i]; cout<<endl; return 0; } 运行结果: a[]: 6 5 3 2 1 b[]: 6 5 3 2 1
对于自定义类型也可以使用sort,但必须提供比较函数。
例如
#include <iostream> #include <algorithm> using namespace std; struct point { int x, y; bool operator < (const point &b)const/**<重载<号,可根据自己需要实现内部代码 */ { if (x == b.x) return y < b.y; return x < b.x; } }; point p[5] = { 1, 2, 1, 1, 4, 8, 2, 3, 4, 6 }; /**< 对p数组进行排序,先按x小的,如果x相等,再按y小的排序 */ int main() { sort(p, p + 5); cout<<"p[]:"; for (int i = 0; i < 5; i++) cout<<'('<<p[i].x<<','<<p[i].y<<')'; cout<<endl; return 0; } 也可以自己用自定义的比较函数或比较对象来排序。 运行结果: p[]:(1,1)(1,2)(2,3)(4,6)(4,8)
下面就来讲讲qsort函数
/**< 对于下面的a数组,如何使用qsort来排序呢,先看看代码实现 */ #include <iostream> #include <algorithm> using namespace std; int a[5] = {2, 1, 3, 5, 6}; int cmp(const void *a, const void *b)/**< 从小到大排序 */ { return ((*(int *)a) - (*(int *)b); } int main() { qsort(a, 5, sizeof(a[0]), cmp); cout<<"a[]:"; for (int i = 0; i < 5; i++) cout<<' '<<a[i]; return 0; } 运行结果: a[]: 1 2 3 5 6
对于整数和字符类型可以直接返回差值,
但对于实数需要注意,因为比较函数返回的是int类型。
例如:
#include <iostream> #include <algorithm> using namespace std; double a[5] = {2.4, 1.5, 3.4, 5.5, 1.6}; int cmp(const void *a, const void *b)/**< 从小到大排序 */ { return (*(double *)a) > (*(double *)b) ? 1 : -1; } int main() { qsort(a, 5, sizeof(a[0]), cmp); cout<<"a[]:"; for (int i = 0; i < 5; i++) cout<<' '<<a[i]; return 0; } 运行结果: a[]: 1.5 1.6 2.4 3.4 5.5
还是先来看看qsort函数原型
_CRTIMP void __cdecl qsort(void*, size_t, size_t, int (*)(const void*, const void*));
对于为何要那样定义比较函数应该有个大概明白了吧。
原型要与int (*)(const void*, const void*)(函数指针的应用)对应。
qsort也可对自定义类型排序
#include <iostream> #include <algorithm> using namespace std; struct point { int x, y; }; point p[5] = { 1, 2, 1, 1, 4, 8, 2, 3, 4, 6 }; int cmp(const void *a, const void *b) { point *pa = (point *)a; point *pb = (point *)b; if (pa->x == pb->y) return pa->y - pb->y; return pa->x - pb->y; } /**< 对p数组进行排序,先按x小的,如果x相等,再按y小的排序 */ int main() { qsort(p, 5, sizeof(p[0]), cmp); cout<<"p[]:"; for (int i = 0; i < 5; i++) cout<<'('<<p[i].x<<','<<p[i].y<<')'; cout<<endl; return 0; } 运行结果: p[]:(1,1)(1,2)(2,3)(4,6)(4,8)
对于其它自定义类型也是类似。
sort和qsort函数的平均时间复杂度都是NlogN,log以2为底。
都在algorithm文件里,同时别忘了使用命名空间
using namespace std。
看到这以后就不用在担心自己不会写排序函数了,学会了这两个函数,应付大部分排序就足够用了。