免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2573 | 回复: 2
打印 上一主题 下一主题

[算法] STL的sort算法,为什么VC的实现选择了用3中不同的实现,而GCC只用了插入排序? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-07 12:43 |只看该作者 |倒序浏览
5可用积分
STL的sort算法,实际调用的算法不管是哪一种,都应该让算法的复杂度保持最低,对吧。
VC的sort源代码实现是,当排序的个数小于8个的时间,直接插入排序,否则用快速排序。快速排序pivot如果递归层数太深,则余下的工作采用堆排序。这样就能达到算法的最优化结果,我贴了代码:

  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.                 _STD 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.         }
复制代码
但是GCC4.4里面的源代码,我看起来都是插入排序啊:


  1.   template<typename _RandomAccessIterator>
  2.     inline void
  3.     sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
  4.     {
  5.       typedef typename iterator_traits<_RandomAccessIterator>::value_type
  6.         _ValueType;

  7.       // concept requirements
  8.       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
  9.             _RandomAccessIterator>)
  10.       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
  11.       __glibcxx_requires_valid_range(__first, __last);

  12.       if (__first != __last)
  13.         {
  14.           std::__introsort_loop(__first, __last,
  15.                                 std::__lg(__last - __first) * 2);
  16.           std::__final_insertion_sort(__first, __last);
  17.         }
  18.     }
复制代码
以及

  1.   /// This is a helper function for the sort routine.
  2.   template<typename _RandomAccessIterator>
  3.     void
  4.     __final_insertion_sort(_RandomAccessIterator __first,
  5.                            _RandomAccessIterator __last)
  6.     {
  7.       if (__last - __first > int(_S_threshold))
  8.         {
  9.           std::__insertion_sort(__first, __first + int(_S_threshold));
  10.           std::__unguarded_insertion_sort(__first + int(_S_threshold), __last);
  11.         }
  12.       else
  13.         std::__insertion_sort(__first, __last);
  14.     }
复制代码
这岂不是会让sort算法的复杂度保持在o(n^2)? GCC的STL实现不该回这么傻吧

最佳答案

查看完整内容

注意std::__introsort_loop,相当于qsort的改进版。必须要看清楚的是,__final_insertion_sort()之前,经过__introsort_loop()的整个序列可以看成是一个个元素个数小于或等于16的子序列(注意子序列长度是不等的),且这些子序列不但内部有相当程度排序,且更重要的是以子序列与子序列之间也是“递增”的,意思是前一个子序列中的元素都是小于后一个子序列中的元素的,所以这个时候运用insertion_sort(),效率可是相当高的。 参见:h ...

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
2 [报告]
发表于 2013-07-07 12:43 |只看该作者
注意std::__introsort_loop,相当于qsort的改进版。必须要看清楚的是,__final_insertion_sort()之前,经过__introsort_loop()的整个序列可以看成是一个个元素个数小于或等于16的子序列(注意子序列长度是不等的),且这些子序列不但内部有相当程度排序,且更重要的是以子序列与子序列之间也是“递增”的,意思是前一个子序列中的元素都是小于后一个子序列中的元素的,所以这个时候运用insertion_sort(),效率可是相当高的。

参见:http://blog.sina.com.cn/s/blog_9d987af501014zlj.html

论坛徽章:
0
3 [报告]
发表于 2013-07-07 13:12 |只看该作者
sort还可能调用 std::__introsort_loop
std::__introsort_loop还可能调用  __partial_sort
上面俩函数定义在std_algo.h中

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP