1、概述
排序算法是算法中的重点,排序过的数据,特别容易查找,不管是实际工作还是面试都会用到它。
现实生活中,字典需要排序,书籍索引需要排序,磁盘目录需要排序,名片需要排序等等。任何数据只要你想快速查找,就需要进行排序。
排序算法有很多种,比如冒泡排序、选择排序、插入排序、快速排序、堆排序。其中堆排序我们在整理 heap 时已经进行整理了,今天主要是对 STL 中的 sort 排序进行整理。而 sort 排序又会用到快速排序等其它一些排序算法,这里就按个,由简到难的进行介绍。
2、partial_sort/partial_sort_copy
partial_sort 局部排序,这个算法接受一个 middle 迭代器(位于序列 [first, last) 之内 ),然后重新安排 [first, last),使序列中 (middle-first)个最小元素以递增顺序排序,置于[first, middle)。其余元素放置在 [middle, last) 中,不保证有任何特定顺序。
partial_sort 的任务是找出 (middle-first) 个最小元素,我们可以把 (middle-first) 组织成一个 max-heap,然后将 [middle, last) 中的每一个元素拿来与 max-heap 的最大值比较,如果小于该最大值,就互换位置并重新保持 max-heap 的状态。这样走到最后,[first, middle) 中的元素肯定就是最小的 (middle-first) 个元素,这时候用 sort_heap() 将 [first, middle) 做一次排序,就得到最后的结果。代码如下:
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>
void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle, RandomAccessIterator last, T*)
{
make_heap(first, middle);
//以下的 i < last 判断操作,只适用于 random iterator
for( RandomAccessIterator i = middle; i < last; ++i)
{
if( *i < *first)
__pop_heap(first, middle, i, T(*i), distance_type(first));
}
sort_heap(first,middle);
}
其中用到的 make_heap、sort_heap、__pop_heap 在整理 heap 时整理过了,大家可以去看看。
partial_sort_copy 和 partial_sort 的行为完全相同,只不过前者不改变原有数据的结构,把排序后的结构置于另一块空间中。这个其实就是从大数据中查找前100大或者小的数据,也叫 Top N 问题。
3、Insertion Sort(插入排序)
插入排序以双层循环的形式进行。外循环遍历整个序列,每次迭代决定出一个子区间;内循环是对这个子区间进行操作,子区间默认是排好序的,新插入的元素与最后的元素进行比较,如果大于就进行交换,然后再向前去比较,如果大于就进行交换,直到小于或等于,序列排序完毕。
插入排序的复杂度为 O(N2)