C++中的 sort函数、函数指针、仿函数

举报
用户已注销 发表于 2021/11/19 04:28:04 2021/11/19
【摘要】 sort函数有2种常见的写法,一种是不带参的,也就是默认的升序,一种是传入函数指针的,用函数自定义排序规则。 示例: #include<iostream>#include<algorithm>#include<functional>using namespace std; class cmp{pu...

sort函数有2种常见的写法,一种是不带参的,也就是默认的升序,一种是传入函数指针的,用函数自定义排序规则。

示例:


  
  1. #include<iostream>
  2. #include<algorithm>
  3. #include<functional>
  4. using namespace std;
  5. class cmp
  6. {
  7. public:
  8. bool operator()(int a, int b) //从小到大
  9. {
  10. return a < b;
  11. }
  12. };
  13. bool cmp2(int a, int b) //从大到小
  14. {
  15. return a > b;
  16. }
  17. int main()
  18. {
  19. int num[4] = { 1, 3, 4, 2 };
  20. sort(num, num + 4);
  21. cout << num[0] << num[1] << num[2] << num[3] << endl;
  22. sort(num, num + 4, cmp2);
  23. cout << num[0] << num[1] << num[2] << num[3] << endl;
  24. sort(num, num + 4, cmp());
  25. cout << num[0] << num[1] << num[2] << num[3] << endl;
  26. sort(num, num + 4, greater<>());
  27. cout << num[0] << num[1] << num[2] << num[3] << endl;
  28. sort(num, num + 4, less<>());
  29. cout << num[0] << num[1] << num[2] << num[3] << endl;
  30. return 0;
  31. }

输出:

1234
4321
1234
4321
1234

 

其中,sort(num, num + 4);是默认的升序排序,

sort(num, num + 4, cmp2);  是传入cmp2这个函数指针,

而sort(num, num + 4, c); 是传入一个对象,对象中包含一个仿函数。

greater<>() 和 less<>() 都是头文件<functional>中的函数。

 

仿函数,就是在类中重载()运算符,使得一个类表现得像一个函数。

C++中的sort函数由于用了模板编程,使得用处非常广泛,而且时间复杂度是O(n log n),效率也很高。

 

附上C++中sort的实现代码:


  
  1. template<class _RanIt,
  2. class _Pr> inline
  3. void sort(_RanIt _First, _RanIt _Last, _Pr _Pred)
  4. { // order [_First, _Last), using _Pred
  5. _DEBUG_RANGE(_First, _Last);
  6. _DEBUG_POINTER(_Pred);
  7. _Sort(_Unchecked(_First), _Unchecked(_Last), _Last - _First, _Pred);
  8. }
  9. // TEMPLATE FUNCTION sort
  10. template<class _RanIt> inline
  11. void sort(_RanIt _First, _RanIt _Last)
  12. { // order [_First, _Last), using operator<
  13. _STD sort(_First, _Last, less<>());
  14. }

可以看出,默认的比较函数就是less<>()

 

再附上其中_Sort函数的代码:


  
  1. template<class _RanIt,
  2. class _Diff,
  3. class _Pr> inline
  4. void _Sort(_RanIt _First, _RanIt _Last, _Diff _Ideal, _Pr _Pred)
  5. { // order [_First, _Last), using _Pred
  6. _Diff _Count;
  7. for (; _ISORT_MAX < (_Count = _Last - _First) && 0 < _Ideal; )
  8. { // divide and conquer by quicksort
  9. pair<_RanIt, _RanIt> _Mid =
  10. _Unguarded_partition(_First, _Last, _Pred);
  11. _Ideal /= 2, _Ideal += _Ideal / 2; // allow 1.5 log2(N) divisions
  12. if (_Mid.first - _First < _Last - _Mid.second)
  13. { // loop on second half
  14. _Sort(_First, _Mid.first, _Ideal, _Pred);
  15. _First = _Mid.second;
  16. }
  17. else
  18. { // loop on first half
  19. _Sort(_Mid.second, _Last, _Ideal, _Pred);
  20. _Last = _Mid.first;
  21. }
  22. }
  23. if (_ISORT_MAX < _Count)
  24. { // heap sort if too many divisions
  25. _STD make_heap(_First, _Last, _Pred);
  26. _STD sort_heap(_First, _Last, _Pred);
  27. }
  28. else if (1 < _Count)
  29. _Insertion_sort(_First, _Last, _Pred); // small
  30. }

可以看出是快速排序、堆排序、插入排序三者的结合。

 

快速排序的优点是平均时间比堆排序快,但时间复杂度是O(n^2),而堆排序的时间复杂度是O(n  log n)

这里的sort函数,平均排序时间非常快,而且时间复杂度是O(n log n)

 

3个排序的结合方法:

(1)深度太深时使用堆排序

_Ideal /= 2, _Ideal += _Ideal / 2;    // allow 1.5 log2(N) divisions

这个注释不对,实际上应该是log(N)/log(4/3)次划分,大概等于2.4 log2(N)

_Ideal 这个量没有具体的含义,它既是一开始等于N,然后每次乘以3/4,当它变为0时我就当做深度太深,剩下的交给堆排序

(2)元素太少时使用插入排序

这里的常量_ISORT_MAX = 32,即当递归到只有32个元素时,对这个小片段采取插入排序。

片段花费时间32*31

如果N个元素分割成N/32个片段,每个片段都是32个元素,都采取插入排序,那么总时间是:

N/32 * 32*31 + N* log2(N/32) = N* (log2(N) +26)

这个结果可以认为就是N* log2(N)

 

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/104823002

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。