已知,set,multiset,map,multimap是由于RB_tree形成的,具有自动排序的功能(具体可见RB_tree红黑树的形成),不用sort排序算法,而且类似的用hash_map形成的unordered_set,unordered_map,unordered_multiset,unordered_multimap是不允许遍历的,所以也用不到排序算法,同样的还有stack,priority_queue。

接下来来看看sort的源码剖析
先来写一个小程序

#include <algorithm>      // 各种算法头文件
#include <iostream> // 标准输入输出流头文件
#include <vector> // vector容器头文件
namespace SORT {
inline bool sort(const int x, const int y) {
return x < y;
}
}
int main() {
std::vector<int> v = { 2, 3, 4, 1, 7 };
// 此处用到了sort的第三参数,compare function,比较函数,我们可以直接写出
sort(v.begin(), v.end(), std::ptr_fun(SORT::sort));
for (auto i: v) { std::cout << i << std::endl; }
return 0;
}

下面来深入以下sort函数(CTRL+鼠标点击)

// 此sort算法是没有第三参数的部分(内置比较算法)

/**
* 排序这个序列
* @brief Sort the elements of a sequence.
* @ingroup sorting_algorithms
* @param __first An iterator.
* @param __last Another iterator.
* @return Nothing.
*
* Sorts the elements in the range @p [__first,__last) in ascending order,
* such that for each iterator @e i in the range @p [__first,__last-1),
* *(i+1)<*i is false.
*
* The relative ordering of equivalent elements is not preserved, use
* @p stable_sort() if this is needed.
*/
template<typename _RandomAccessIterator>
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_LessThanComparableConcept<
typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive(__first, __last);

std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
}
// 此为有比较函数参数的部分
/**
* 简单的使用一个比较谓语来排序这个序列元素
* @brief Sort the elements of a sequence using a predicate for comparison.
* 忽略排序算法
* @ingroup sorting_algorithms
* __first:一个迭代器
* @param __first An iterator.
* __last:一个迭代器
* @param __last Another iterator.
* __comp:一个比较函数
* @param __comp A comparison functor.
* 没有返回值
* @return Nothing.
* 把在[__first, __last)范围内的元素进行升序排序,注意,容器的last最后一个元素是空的,因此取开区间
* Sorts the elements in the range @p [__first,__last) in ascending order,
* such that @p __comp(*(i+1),*i) is false for every iterator @e i in the
* range @p [__first,__last-1).
* 等价元素的相对顺序没有保留,如果需要使用stable_sort算法(此处不做解释)
* The relative ordering of equivalent elements is not preserved, use
* @p stable_sort() if this is needed.
*/
// _RandomAccessIterator:迭代器类型之一
// _Compare:比较函数
template<typename _RandomAccessIterator, typename _Compare>
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
typename iterator_traits<_RandomAccessIterator>::value_type,
typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);

std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
}

先来看看有第三参数的排序算法

// _RandomAccessIterator:迭代器类型之一
// _Compare:比较函数
template<typename _RandomAccessIterator, typename _Compare>
inline void
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_BinaryPredicateConcept<_Compare,
typename iterator_traits<_RandomAccessIterator>::value_type,
typename iterator_traits<_RandomAccessIterator>::value_type>)
__glibcxx_requires_valid_range(__first, __last);
__glibcxx_requires_irreflexive_pred(__first, __last, __comp);

std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));
}

此处简略的说明一下__glibcxx_function_requires这个宏定义

显然concept checking不是C++11标准的一部分,它是Boost的一部分,是Boost Concept Checking Library的内容,然后GNU将其整合到了 GNU C++ library中。gcc里面,concept checking默认是关闭的,可以通过 #define _GLIBCXX_CONCEPT_CHECKS 来打开它,但是没有任何必要,因为C++11的特性会完成concept checking的功能

简而言之,这个concept check的作用是“限制某类型的特定的操作是合法的”。比如说,__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<_RandomAccessIterator>)就是要限制你传入的迭代器类型得是Mutable RandomAccessIterator,得支持++ – [] * += -= 等运算符操作。如果不满足的话,编译就不通过。

上面的sort(__first, __last)里的两条__glibcxx_function_requires就限制了:

  • 迭代器类型得是Mutable RandomAccessIterator
  • 迭代器所指类型得是支持<运算符的

可是,这个Mutable RandomAccessIterator又是什么呢?在iterator定义的五种迭代器没有这个玩意。

mutable iterator指的支持write和increment的迭代器。因此,iterator_catogory是random_access_iterator_tag的迭代器并不一定可写,random_access_iterator_tag并不能保证迭代器是mutable还是constant,只有mutable iterator才是可写的。所以上面的两个问题有答案了。

接下来来进入std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp));的代码区

template<typename _RandomAccessIterator, typename _Compare>
inline void
__sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
{
if (__first != __last)
{
// 快速排序 + 堆排序 + 插入排序
std::__introsort_loop(__first, __last,
std::__lg(__last - __first) * 2,
__comp);
// 在区间基本有序的基础上再做一遍插入排序,使区间完全有序
std::__final_insertion_sort(__first, __last, __comp);
}
}

此处有必须要注意一个东西:std::__lg(__last - __first) * 2
计算递归深度,用来控制分割恶化,当递归深度达到该值改用堆排序,因为堆排序是时间复杂度恒定为nlogn。
当进行快速排序的时候,时间复杂度不是稳定的nlogn,最坏情况会变成n^2,因此为了避免最坏的情况,使用堆排序

template<typename _Size>
inline _Size
__lg(_Size __n)
{
_Size __k;
for (__k = 0; __n != 1; __n >>= 1)
++__k;
return __k;
}

快速排序 + 堆排序+插入排序

enum { _S_threshold = 16 };

template<typename _RandomAccessIterator, typename _Size, typename _Compare>
void
__introsort_loop(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Size __depth_limit, _Compare __comp)
{
// 若区间大小<=16就不再排序。
while (__last - __first > int(_S_threshold))
{
// 若递归次数达到限制,就改用堆排序
if (__depth_limit == 0)
{
std::__partial_sort(__first, __last, __last, __comp);
return;
}
--__depth_limit;
_RandomAccessIterator __cut =
std::__unguarded_partition_pivot(__first, __last, __comp); // 分割
std::__introsort_loop(__cut, __last, __depth_limit, __comp); // 右半区间递归
__last = __cut;
// 回到while循环,对左半区间进行排序,这么做能显著减少__introsort_loop的调用的次数
}
}


template<typename _RandomAccessIterator, typename _Compare>
void
__final_insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
if (__last - __first > int(_S_threshold)) // 区间长度大于16
{
// 插入排序
std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
// 也是插入排序,只是在插入排序的内循环时,不再判断边界条件,因为已经保证了区间前面肯定有比待插入元素更小的元素
std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
__comp);
}
else // 区间长度小于等于16的话
std::__insertion_sort(__first, __last, __comp); // 插入排序
}

第一次排序完成后,再进行一次插入排序:std::__final_insertion_sort(__first, __last, __comp);,在区间基本有序的基础上再做一遍插入排序,使区间完全有序

/// This is a helper function for the sort routine.
template<typename _RandomAccessIterator, typename _Compare>
void
__final_insertion_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last, _Compare __comp)
{
if (__last - __first > int(_S_threshold))
{
// 插入排序
std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
// 也是插入排序,只是在插入排序的内循环时,不再判断边界条件,因为已经保证了区间前面肯定有比待插入元素更小的元素
std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
__comp);
}
else
// 插入排序
std::__insertion_sort(__first, __last, __comp);
}