STL源码剖析:5.算法


1.简介

以有限的步骤解决逻辑或数学上的问题,这一专门的科目被称为算法。本章讨论的就是一些被收录于STL中,极具复用价值的算法(以下仅有部分算法)


2.数值算法

2.1 算法accumulate用来计算init和[first,last)内所有元素的总和,也就是累加返回总和即可,在某些不可以直接进行加操作的类型中,需要传入相应的仿函数,由仿函数完成类似于加的操作。

template<class Iterator, class T>
T accumulate(Iterator first, Iterator last, T value) {
	for (; first != last; ++first) {
		value += *first;
	}
	return value;
}

//对于不能直接使用+的元素类型需要提供其指定的accumulate版本
template <class Iterator, class T, class BinaryOperation>
T accumulate(Iterator first, Iterator last, T value, BinaryOperation binary_op) {
	for (; first != last; ++first) {
		value = binary_op(value, *first);
	}
	return value;
}

2.2 算法adjacent_difference用来计算[first,last)中相邻元素的差额,这个函数需要传入一个目标地址用于存储我们最后计算出来的差额,具体操作就是相邻的两个元素相减后的结果存放在目标数组当中,同样的在无法直接相减的时候需要通过传入的仿函数来执行类型的操作。

template<class InputIterator, class OutputIterator>
OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result) {
	if (first == last) return result;
	*result = *first;
	typename iterator_traits<InputIterator>::value_type value = *first;
	while (++first != last) {
		typename iterator_traits<InputIterator>::value_type tmp = *first;
		*++result = tmp - value;
		value = tmp;
	}
	return ++result;
}

template<class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator adjacent_difference(InputIterator first, InputIterator last, 
	OutputIterator result, BinaryOperation binary_op) {
	if (first == last) return result;
	*result = *first;
	typename iterator_traits<InputIterator>::value_type value = *first;
	while (++first != last) {
		typename iterator_traits<InputIterator>::value_type tmp = *first;
		*++result = binary_op(tmp,value);
		value = tmp;
	}
	return ++result;
}

2.3 算法inner_product计算两个容器元素之间的内积,即两个长度相同的容器之间两两相乘,然后将所有相乘结果之和返回,同样的在特定的情况下需要通过传入的仿函数来完成对应的内积操作。

template<class InputIterator1, class InputIterator2, class T>
T inner_product(InputIterator1 first, InputIterator1 last, InputIterator2 first1, T value) {
	for (; first < last; ++first, ++first1) {
		value += (*first * *first1);
	}
	return value;
}

template <class InputIterator1, class InputIterator2, class T, class BinaryOperation>
T inner_product(InputIterator1 first, InputIterator1 last, InputIterator2 first1, 
	T value, BinaryOperation binary_op) {
	for (; first != last; ++first, ++first1) {
		value += binary_op(*first, *first1);
	}
	return value;
}

2.4 算法partial_sum来计算局部总和,即将指定范围内的元素总和返回至目标容器中,如果不能直接进行求和操作的话就需要通过传入的仿函数来完成对应的功能。

template <class InputIterator, class OutputIterator>
OutputIterator partial_sum(InputIterator first, InputIterator last, OutputIterator result) {
	if (first == last) return result;
	*result = *first;
	typename iterator_traits<InputIterator>::value_type value = *first;
	while (++first != last) {
		value += *first;
		*++result = value;
	}

	return ++result;
}

template <class InputIterator, class OutputIterator, class BinaryOperation>
OutputIterator partial_sum(InputIterator first, InputIterator last,
	OutputIterator result, BinaryOperation binary_op) {
	if (first == last) return result;
	*result = *first;
	typename iterator_traits<InputIterator>::value_type value = *first;
	while (++first != last) {
		value = binary_op(value, *first);
		*++result = value;
	}

	return ++result;
}

3.基本算法

3.1 lexicographical_compare算法是以“字典排列方式”对两个序列进行比较,比较操作针对两序列中的对应位置上的元素进行,并持续到一下三种情况:
①:某一组对应元素彼此不相等
②:同时到达last1和last2(两序列的大小相同)
③:到达last1或last2(两序列大小不同)

template <class InputIter1, class InputIter2>
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
	InputIter2 first2, InputIter2 last2)
{
	for (; first1 != last1 && first2 != last2; ++first1, ++first2)
	{
		if (*first1 < *first2)//第一序列元素值小于第二序列相应元素值
			return true;
		if (*first2 < *first1)//第二序列元素值小于第一序列元素值
			return false;
	}
	return first1 == last1 && first2 != last2;
}

// 重载版本使用函数对象 comp 代替比较操作
template <class InputIter1, class InputIter2, class Compred>
bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
	InputIter2 first2, InputIter2 last2, Compred comp)
{
	for (; first1 != last1 && first2 != last2; ++first1, ++first2)
	{
		if (comp(*first1, *first2))
			return true;
		if (comp(*first2, *first1))
			return false;
	}
	return first1 == last1 && first2 != last2;
}

// 针对 const unsigned char* 的特化版本
bool lexicographical_compare(const unsigned char* first1,
	const unsigned char* last1,
	const unsigned char* first2,
	const unsigned char* last2)
{
	const auto len1 = last1 - first1;
	const auto len2 = last2 - first2;
	// 先比较相同长度的部分
	const auto result = std::memcmp(first1, first2, ministl::min(len1, len2));
	// 若相等,长度较长的比较大
	return result != 0 ? result < 0 : len1 < len2;
}

3.2 copy算法可以将输入区间的元素复制到输出区间,注意如果输出区间的起点位与输入区间内,copy算法便可能会在输入区间的某些元素尚未被复制之前就覆盖其值导致结果错误。

template <class InputIter, class OutputIter>
OutputIter
_copy_cat(InputIter first, InputIter last, OutputIter result,
	ministl::input_iterator_tag)
{
	for (; first != last; ++first, ++result)
	{
		*result = *first;
	}
	return result;
}

// ramdom_access_iterator_tag 版本
template <class RandomIter, class OutputIter>
OutputIter
_copy_cat(RandomIter first, RandomIter last, OutputIter result,
	ministl::random_access_iterator_tag)
{
	for (auto n = last - first; n > 0; --n, ++first, ++result)
	{
		*result = *first;
	}
	return result;
}

template <class InputIter, class OutputIter>
OutputIter
_copy(InputIter first, InputIter last, OutputIter result)
{
	return _copy_cat(first, last, result, iterator_category(first));
}


// 为 trivially_copy_assignable 类型提供特化版本
template <class Tp, class Up>
typename std::enable_if<
	std::is_same<typename std::remove_const<Tp>::type, Up>::value&&
	std::is_trivially_copy_assignable<Up>::value,
	Up*>::type
	_copy(Tp* first, Tp* last, Up* result)
{
	const auto n = static_cast<size_t>(last - first);
	if (n != 0)
		std::memmove(result, first, n * sizeof(Up));
	return result + n;
}

template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
	return _copy(first, last, result);
}

//针对char以及wchar_t的特化版本,因为调用memmove的速度在char类型时速度更快
inline char* copy(const char* first, const char* last, char* result) {
	memmove(result, first, last - first);
	return result + (last - first);
}

inline wchar_t* copy(const wchar_t* first, const wchar_t* last, wchar_t* result) {
	memmove(result, first, sizeof(wchar_t) * (last - first));
	return result + (last - first);
}

4.set相关算法

//**********************	set容器算法		******************
//1.将两个set并在一起set_union
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_union(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result) {
	while (first1 != last1 && first2 != last2) {
		if (*first1 < *first2) {
			*result = *first1;
			++first1;
		}
		else if (*first2 < *first1) {
			*result = *first2;
			++first2;
		}
		else {
			*result = *first1;
			++first1;
			++first2;
		}
		++result;
	}

	return copy(first2, last2, copy(first1, last1, result));
}

template <class InputIterator1, class InputIterator2, class OutputIterator, class Comp>
OutputIterator set_union(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result, Comp cp) {
	while (first1 != last1 && first2 != last2) {
		if (cp(*first1, *first2)) {
			*result = *first1;
			++first1;
		}
		else if (cp(*first2,*first1)) {
			*result = *first2;
			++first2;
		}
		else {
			*result = *first1;
			++first1;
			++first2;
		}
		++result;
	}

	return copy(first2, last2, copy(first1, last1, result));
}

//2.将两个集合交在一起set_intersection
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result) {
	while (first1 != last1 && first2 != last2) {
		if (*first1 < *first2) {
			++first1;
		}
		else if (*first2 < *first1) {
			++first2;
		}
		else {
			*result = *first1;
			++first1;
			++first2;
			++result;
		}
	}

	return result;
}

template <class InputIterator1, class InputIterator2, class OutputIterator, class Comp>
OutputIterator set_intersection(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result, Comp cp) {
	while (first1 != last1 && first2 != last2) {
		if (cp(*first1,*first2)) {
			++first1;
		}
		else if (cp(*first2,*first1)) {
			++first2;
		}
		else {
			*result = *first1;
			++first1;
			++first2;
			++result;
		}
	}

	return result;
}

//3.两个set之间的差集set_difference()
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_difference(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result) {
	while (first1 != last1 && first2 != last2) {
		if (*first1 < *first2) {
			*result = *first1;
			++first1;
			++result;
		}
		else if (*first2 < *first1) {
			++first2;
		}
		else {
			++first1;
			++first2;
		}
	}

	return copy(first1, last1, result);
}

template <class InputIterator1, class InputIterator2, class OutputIterator, class Comp>
OutputIterator set_difference(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result, Comp cp) {
	while (first1 != last1 && first2 != last2) {
		if (cp(*first1,*first2)) {
			*result = *first1;
			++first1;
			++result;
		}
		else if (cp(*first2,*first1)) {
			++first2;
		}
		else {
			++first1;
			++first2;
		}
	}

	return copy(first1, last1, result);
}

//4. 对称差集 出现于s1但不出现在s2以及出现在s2不出现在s1的元素set_sysmmetric_difference
template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_symmetric_difference(InputIterator1 first1, InputIterator2 last1,
	InputIterator2 first2, InputIterator2 last2, OutputIterator result) {
	while (first1 != last1 && first2 != last2) {
		if (*first1 < *first2) {
			*result = *first1;
			++first1;
			++result;
		}
		else if (*first2 < *first1) {
			*result = *first2;
			++first2;
			++result;
		}
		else {
			++first1;
			++first2;
		}
	}

	return copy(first2, last2, copy(first1, last1, result));
}

5. 其他算法

5.1.rotate算法将[first, middle)内的元素和[middle,last)内的元素互换,middle所值的元素会成为容器的第一个元素。

template<class ForwardIterator>
inline void rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator last) {
	if (first == middle || middle == last) return;
	_rotate(first, middle, last, distance_type(first), iterator_category(first));
}

template <class ForwardIterator , class Distance>
void _rotate
(ForwardIterator first, ForwardIterator middle, ForwardIterator last, Distance*, forward_iterator_tag) {
	for (ForwardIterator i = middle;;) {
		iter_swap(first, i);
		++first;
		++i;
		// 一下判断是前段[first, middle]先结束还是后段[middle,last]先结束
		if (first == middle) {//前短结束了
			if (i == last) return;//如果后段同时也结束,整个就结束了
			middle = i;//否则调整,对新的前后段再作交换
		}
		else if (i == last){
			i = middle;
		}
	}
}

template <class BidirectionalIterator, class Distance>
void _rotate
(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Distance*, bidirectional_iterator_tag) {
	reverse(first, middle);
	reverse(middle, last);
	reverse(first, last);
}

template <class EuclideanRingElement>
EuclideanRingElement _gcd(EuclideanRingElement m, EuclideanRingElement n) {
	while (n != 0) {
		EuclideanRingElement t = m % n;
		m = n;
		n = t;
	}
	return m;
}

template <class RandomAccessIterator, class Distance, class T>
void _rotate_cycle(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator initial, Distance shift, T*) {
	T value = *initial;
	RandomAccessIterator ptr1 = initial;
	RandomAccessIterator ptr2 = ptr1 + shift;
	while (ptr2 != initial) {
		*ptr1 = *ptr2;
		ptr1 = ptr2;
		if (last - ptr2 > shift)
			ptr2 += shift;
		else
			ptr2 = first + (shift - (last - ptr2));
	}
	*ptr1 = value;
}

template<class RandomAccessIterator, class Distance>
void _rotate
(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, Distance*, random_access_iterator_tag) {
	Distance n = _gcd(last - first, middle - first);
	while (n--) {
		_rotate_cycle(first, last, first + n, middle - first, value_type(first));
	}
}

5.2 search_n算法,在序列所覆盖的区间内查找连续count个符合条件的元素形成的子序列,并且返回一个迭代器指向该子序列起始处,找不到的话就返回last。

template <class ForwardIterator, class Integer, class T>
ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Integer count, const T& value) {
	if (count <= 0)
		return first;
	else {
		first = find(first, last, value);//首先找出value第一次出现点
		while (first != last) {//继续查找余下元素
			Integer n = count - 1;//value还应出现n次
			ForwardIterator i = first;//从上次出现点接下去查找
			++i;
			while (i != last && n != 0 && *i == value) {//下一个元素是value
				++i;
				--n;
			}
			if (n == 0)//满足条件
				return first;
			else
				first = find(i, last, value);//在剩余的区间寻找下一个出现点
		}
		return last;
	}
}

template <class ForwardIterator, class Integer, class T, class BinaryPredicate>
ForwardIterator search_n
(ForwardIterator first, ForwardIterator last, Integer count, const T& value, BinaryPredicate binary_pred) {
	if (count <= 0)
		return first;
	else {
		while (first != last) {
			if (binary_pred(*first, value))
				break;
		}
		while (first != last) {
			Integer n = count - 1;
			ForwardIterator i = first;
			++i;
			while (i != last && n != 0 && binary_pred(*i,value)) {
				++i;
				--n;
			}
			if (n == 0)
				return first;
			else {
				while (i != last) {
					if (binary_pred(*i, value)) break;
					++i;
				}
				first = i;
			}
		}

		return last;
	}
}

5.3 lower_bound算法,这是二分法的一个版本,试图在已排序的[first,last)中寻找元素,如果具有与value相等的元素就返回一个迭代器指向第一个相等的元素,又因为这个算法是应用于有序序列的,因此它意为寻找一个不小于value的第一个元素。

template<class Forwarditerator, class T, class Distance>
Forwarditerator _lower_bound
(Forwarditerator first, Forwarditerator last, const T& value, Distance*, forward_iterator_tag) {
	Distance len = 0;
	distance(first, last, len);
	Distance half;
	Forwarditerator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first;
		advance(middle, half);
		if (*middle < value) {
			first = middle;
			++first;
			len = len - half - 1;
		}
		else {
			len = half;
		}
	}
	return first;
}

template <class RandomAccessIterator, class T, class Distance>
RandomAccessIterator _lower_bound
(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) {
	Distance len = last - first;
	Distance half;
	RandomAccessIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first + half;
		if (*middle < value) {
			first = middle + 1;
			len = len - half - 1;
		}
		else {
			len = half;
		}
	}
	return first;
}

template<class Forwarditerator, class T, class Distance, class Compare>
Forwarditerator _lower_bound
(Forwarditerator first, Forwarditerator last, const T& value, Compare comp, Distance*, forward_iterator_tag) {
	Distance len = 0;
	ministl::distance(first, last, len);
	Distance half;
	Forwarditerator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first;
		advance(middle, half);
		if (comp(*middle < value)) {
			first = middle;
			++first;
			len = len - half - 1;
		}
		else {
			len = half;
		}
	}
	return first;
}

template <class RandomAccessIterator, class T, class Distance,class Compare>
RandomAccessIterator _lower_bound
(RandomAccessIterator first, RandomAccessIterator last, const T& value, Compare comp, Distance*, random_access_iterator_tag) {
	Distance len = last - first;
	Distance half;
	RandomAccessIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first + half;
		if (comp(*middle,value)) {
			first = middle + 1;
			len = len - half - 1;
		}
		else {
			len = half;
		}
	}
	return first;
}

template <class ForwardIter, class T>
ForwardIter
lower_bound(ForwardIter first, ForwardIter last, const T& value)
{
	return ministl::_lower_bound(first, last, value, distance_type(first), iterator_category(first));
}

template <class ForwardIterator, class T, class Compare>
inline ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) {
	return ministl::_lower_bound(first, last, value, comp, distance_type(first), iterator_category(first));
}

5.4 upper_bound算法也是二分查找的一个版本,但是与上一个不同的是,他是找出大于value的第一个元素的位置,具体代码都是类似的。

template<class ForwardIterator, class T,class Compare, class Distance>
ForwardIterator _upper_bound
(ForwardIterator first, ForwardIterator last, const T& value, Compare comp, Distance*, forward_iterator_tag) {
	Distance len = 0;
	distance(first, last, len);
	Distance half;
	ForwardIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first;
		advance(middle, half);
		if (comp(value ,*middle)) {
			len = half;
		}
		else {
			first = middle;
			++first;
			len = len - half - 1;
		}
	}
	return first;
}

template<class RandomAccessIterator, class T, class Distance, class Compare>
RandomAccessIterator _upper_bound
(RandomAccessIterator first, RandomAccessIterator last, const T& value, Compare comp, Distance*, random_access_iterator_tag) {
	Distance len = last - first;
	Distance half;
	RandomAccessIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first + half;
		if (comp(value,*middle))
			len = half;
		else {
			first = middle + 1;
			len = len - half - 1;
		}
	}
	return first;
}

template<class ForwardIterator, class T, class Distance>
ForwardIterator _upper_bound
(ForwardIterator first, ForwardIterator last, const T& value, Distance*, forward_iterator_tag) {
	Distance len = 0;
	distance(first, last, len);
	Distance half;
	ForwardIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first;
		advance(middle, half);
		if (value < *middle) {
			len = half;
		}
		else {
			first = middle;
			++first;
			len = len - half - 1;
		}
	}
	return first;
}

template<class RandomAccessIterator, class T, class Distance>
RandomAccessIterator _upper_bound
(RandomAccessIterator first, RandomAccessIterator last, const T& value, Distance*, random_access_iterator_tag) {
	Distance len = last - first;
	Distance half;
	RandomAccessIterator middle;

	while (len > 0) {
		half = len >> 1;
		middle = first + half;
		if (value < *middle)
			len = half;
		else {
			first = middle + 1;
			len = len - half - 1;
		}
	}
	return first;
}

template <class ForwardIterator, class T>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value) {
	return _upper_bound(first, last, value, distance_type(first), iterator_category(first));
}

template <class ForwardIterator, class T, class Compare>
inline ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& value, Compare comp) {
	return _upper_bound(first, last, value, comp, distance_type(first), iterator_category(first));
}

5.5 sort算法
①:insertion sort算法以双层循环的方式进行,外循环遍历整个序列,内循环遍历子序列,将子区间中的每一个逆转对。

// 默认以渐增方式排序  
template <class RandomAccessIterator>  
void __insertion_sort(RandomAccessIterator first,  
    RandomAccessIterator last)  
{  
    if (first == last) return;  
               // --- insertion sort 外循环 ---  
    for (RandomAccessIterator i = first + 1; i != last; ++i)  
        __linear_insert(first, i, value_type(first));  
    // 以上,[first,i) 形成一个子区间  
}  
  
template <class RandomAccessIterator, class T>  
inline void __linear_insert(RandomAccessIterator first,  
    RandomAccessIterator last, T*)  
{  
    T value = *last;      // 记录尾元素  
    if (value < *first){   // 尾比头还小 (注意,头端必为最小元素)  
        copy_backward(first, last, last + 1);   // 将整个区间向右移一个位置  
        *first = value;   // 令头元素等于原先的尾元素值  
    }  
    else    // 尾不小于头  
        __unguarded_linear_insert(last, value);  
}  
  
template <class RandomAccessIterator, class T>  
void __unguarded_linear_insert(RandomAccessIterator last, T value)  
{  
    RandomAccessIterator next = last;  
    --next;  
  
    // --- insertion sort 内循环 ---  
    // 注意,一旦不再出现逆转对(inversion),循环就可以结束了  
    while (value < *next){   // 逆转对(inversion)存在  
        *last = *next;      // 调整  
        last = next;        // 调整迭代器      
        --next;         // 左移一个位置  
    }  
    *last = value;          // value 的正确落脚处  
}  

②:Quick Sort是目前已知最快的排序法,平均复杂度为O(NlogN),可是最坏情况下将达O(N^2)。
Quick Sort算法可以叙述如下。假设S代表将被处理的序列:
1、如果S的元素个数为0或1,结束。
2、取S中的任何一个元素,当做枢轴(pivot) v。
3、将S分割为L、R两段,使L内的每一个元素都小于或等于v,R内的每一个元素都大于或等于v。
4、对L、R递归执行Quick Sort。
Median-of-Three(三点中值):
因为任何元素都可以当做枢轴(pivot),为了避免元素输入时不够随机带来的恶化效应,最理想最稳当的方式就是取整个序列的投、尾、中央三个元素的中值(median)作为枢轴。这种做法称为median-of-three partitioning,源码如下:

// 返回 a,b,c之居中者  
template <class T>  
inline const T& __median(const T& a, const T& b, const T& c)  
{  
    if (a < b)  
        if (b < c)       // a < b < c  
            return b;  
        else if (a < c)  // a < b, b >= c, a < c  -->     a < b <= c  
            return c;  
        else            // a < b, b >= c, a >= c   -->   c <= a < b  
            return a;  
    else if (a < c)      // c > a >= b  
        return a;  
    else if (b < c)      // a >= b, a >= c, b < c   -->   b < c <= a  
        return c;  
    else                // a >= b, a >= c, b >= c  -->    c<= b <= a  
        return b;         
} 

Partitioning(分割)
分割方法有很多,以下叙述既简单又有良好成效的做法。令first向尾移动,last向头移动。当first大于或等于pivot时停下来,当last小于或等于pivot时也停下来,然后检验两个迭代器是否交错。未交错则元素互相,然后各自调整一个位置,再继续相同行为。若交错,则以此时first为轴将序列分为左右两半,左边值都小于或等于pivot,右边都大于等于pivot。源代码如下:

template <class RandomAccessIterator, class T>  
RandomAccessIterator __unguarded_partition(  
                                RandomAccessIterator first,  
                                RandomAccessIterator last,  
                                T pivot)  
{  
    while(true){  
        while (*first < pivot) ++first;  // first 找到 >= pivot的元素就停  
        --last;  
  
        while (pivot < *last) --last;    // last 找到 <=pivot  
  
        if (!(first < last)) return first;   // 交错,结束循环    
    //  else  
        iter_swap(first,last);              // 大小值交换  
        ++first;                            // 调整  
    }  
}  

③:Heap Sort

// paitial_sort的任务是找出middle - first个最小元素。  
template <class RandomAccessIterator>  
inline void partial_sort(RandomAccessIterator first,  
                         RandomAccessIterator middle,  
                         RandomAccessIterator last)  
{  
    __partial_sort(first, middle, last, value_type(first));  
}  
template <class RandomAccessIterator,class T>  
inline void __partial_sort(RandomAccessIterator first,  
                        RandomAccessIterator middle,  
                        RandomAccessIterator last, T*)  
{  
    make_heap(first, middle); // 默认是max-heap,即root是最大的  
    for (RandomAccessIterator i = middle; i < last; ++i)  
        if (*i < *first)  
            __pop_heap(first, middle, i, T(*i), distance_type(first));  
    sort_heap(first,middle);  
}  

④:IntroSort:不当的枢轴选择,导致不当的分割,导致Quick Sort恶化为O(N^2)。David R. Musser于1996年提出一种混合式排序算法,Introspective Sorting。其行为在大部分情况下几乎与 median-of-3 Quick Sort完全相同。但是当分割行为(partitioning)有恶化为二次行为倾向时,能自我侦测,转而改用Heap Sort,使效率维持在O(NlogN),又比一开始就使用Heap Sort来得好。大部分STL的sort内部其实就是用的IntroSort,源码如下:

template <class RandomAccessIterator>  
inline void sort(RandomAccessIterator first,  
                RandomAccessIterator last)  
{  
    if (first != last){  
        __introsort_loop(first, last, value_type(first), __lg(last-first)*2);  
        __final_insertion_sort(first,last);  
    }  
                                                                                                      
}  
// __lg()用来控制分割恶化的情况  
// 找出2^k <= n 的最大值,例:n=7得k=2; n=20得k=4  
template<class Size>  
inline Size __lg(Size n)  
{  
    Size k;  
    for (k = 0; n > 1; n >>= 1)   
        ++k;  
    return k;  
}  
  
       // 当元素个数为40时,__introsort_loop的最后一个参数  
       // 即__lg(last-first)*2是5*2,意思是最多允许分割10层。  
  
const int  __stl_threshold = 16;  
  
template <class RandomAccessIterator, class T, class Size>  
void __introsort_loop(RandomAccessIterator first,  
                RandomAccessIterator last, T*,   
                Size depth_limit)  
{  
    while (last - first > __stl_threshold){      // > 16  
        if (depth_limit == 0){                  // 至此,分割恶化  
            partial_sort(first, last, last);    // 改用 heapsort  
            return;  
        }  
  
        --depth_limit;  
        // 以下是 median-of-3 partition,选择一个够好的枢轴并决定分割点  
        // 分割点将落在迭代器cut身上  
        RandomAccessIterator cut = __unguarded_partition  
            (first, last, T(__median(*first,  
                                     *(first + (last - first)/2),  
                                    *(last - 1))));  
  
        // 对右半段递归进行sort  
        __introsort_loop(cut,last,value_type(first), depth_limit);  
  
        last = cut;  
        // 现在回到while循环中,准备对左半段递归进行sort  
        // 这种写法可读性较差,效率也并没有比较好  
    }  
}  

函数一开始就判断序 列大小,通过个数检验之后,再检测分割层次,若分割层次超过指定值,就改用partial_sort(),即Heap sort。都通过了这些校验之后,便进入与Quick Sort完全相同的程序。
当__introsort_loop()结束,[first,l ast)内有多个“元素个数少于或等于”16的子序列,每个序列有相当程序的排序,但尚未完全排序(因为元素个数一旦小于 __stl_threshold,就被中止了)。回到母函数,再进入__final_insertion_sort():

template <class RandomAccessIterator>  
void __final_insertion_sort(RandomAccessIterator first,  
    RandomAccessIterator last)  
{  
    if (last - first > __stl_threshold){     
        // > 16  
        // 一、[first,first+16)进行插入排序  
        // 二、调用__unguarded_insertion_sort,实质是直接进入插入排序内循环,  
        //     *参见Insertion sort 源码  
        __insertion_sort(first,first + __stl_threshold);  
        __unguarded_insertion_sort(first + __stl_threshold, last);  
    }  
    else  
        __insertion_sort(first, last);  
}  
  
template <class RandomAccessIterator>  
inline void __unguarded_insertion_sort(RandomAccessIterator first,  
    RandomAccessIterator last)  
{  
    __unguarded_insertion_sort_aux(first, last, value_type(first));  
}  
  
template <class RandomAccessIterator, class T>  
  
void __unguarded_insertion_sort_aux(RandomAccessIterator first,  
    RandomAccessIterator last,  
    T*)  
{  
    for (RandomAccessIterator i = first; i != last; ++i)  
        __unguarded_linear_insert(i, T(*i));  
}  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值