写在前面
在STL的sort算法中,本以为是使用quick sort算法实现的,但是仔细一个实质上而是使用introSort算法实现的,这种算法可以根据递归的深度来决定是否还是使用quick sort,如果递归的深度过深,则在对应区间上使用heap sort算法来实现
并且,我们知道在执行完多次qucik sort之后,数组相邻之间需要改动的并不是很多,如果我们继续递归下去,不仅仅是浪费空间,并且在时间上相对来说也十分浪费,这里不如直接采用O(n^2)的算法更快(在数组较短的时候,O(n^2)的算法要比quick sort更快一些),当然在introSort算法中,对O(n^2)的算法也有一定的优化
算法解释
算法首先判断排序节点个数,当小于16个时,直接使用O(n^2)的算法,否则使用quick sort,但是这里的quick sort会根据递归的深度来进行自动判断,当超出递归限度的时候,直接在对应区间调用heap sort算法,否则否则继续向深处递归。
当quick sort执行完后前后长度小于16时,不再进行递归,而是使用O(n^2)的算法对区间执行最后的整体整合即可实现intorSort算法。
复杂度
Name | Best | Average | Worst | Memory | Stability |
内省排序 | nlogn | nlogn | nlogn | n |
not stable |
具体实现
文件:_insertion_sort.h
/*
* 简单的插入排序实现
* created by A_Bo
*/
#ifndef _INSERTION_SORT_H_INCLUDED
#define _INSERTION_SORT_H_INCLUDED
#include <iostream>
template<class T>
inline void copy_backward(T first,T last, T result){ //背后的容器为简单的数组,没有考虑任何容器大小问题,
while(--last != first) //只是简单的”实现“了函数的功能
*--result = *last;
*--result = *last;
}
template<class T>
void __unguarded_liner_insert(T last, int value){ //没有条件限制的向前移动,少了一个条件的判断,
T next = last; //因为前面已经进行了条件的判断,及最前面的元素一定大于value
--next;
while(value < *next){
*last = *next;
last = next;
--next;
}
*last = value;
}
template<class T>
inline void __liner_insert(T first,T last){
int value = *last;
if(value < *first){ //如果最后一个元素小于第一个元素,直接和第一个元素做交换
copy_backward(first,last,last+1);
*first = value;
}
else //否则没有条件限制地向前进行判断交换操作
__unguarded_liner_insert(last,value);
}
template<class T>
void __insertion_sort(T first,T last){
if(last == first) return ;
for(T i = first+1 ; i != last ; ++i)
__liner_insert(first,i); //在区间[first,i]进行插入排序,讲*i插入当区间相应的位置
}
#endif // _INSERTION_SORT_H_INCLUDED
文件名:_heap_sort.h
/*
*堆排序算法,参考https://blog.csdn.net/li1615882553/article/details/83277847
*简单的实现了make_heap、sort_heap两个基本功能
*created by A_Bo
*/
#ifndef _HEAP_SORT_H_INCLUDED
#define _HEAP_SORT_H_INCLUDED
#include "_insertion_sort.h"
template<class T>
void __push_heap(T first,int holdIndex,int value){
int parent = (holdIndex - 1) / 2;
while(holdIndex > 0 && *(first + parent) < value){
*(first + holdIndex) = *(first + parent);
holdIndex = parent;
parent = (holdIndex - 1) / 2;
}
*(first + holdIndex) = value;
}
template<class T>
void __adjust_heap(T first,int holdIndex,int len, int value){
int secondChild = 2 * (holdIndex + 1);
while(secondChild < len){
if(*(first + secondChild - 1) > *(first + secondChild))
secondChild --;
*(first+holdIndex) = *(first + secondChild);
holdIndex = secondChild;
secondChild = 2 * (holdIndex + 1);
}
if(secondChild == len){
*(first + holdIndex) = *(first + secondChild - 1);
holdIndex = secondChild - 1;
}
__push_heap(first,holdIndex,value);
}
template <class T>
void __make_heap(T first,T last){
if(last - first < 2) return ; //只包含一个元素
int len = last - first;
int holdIndex = (len - 2) / 2;
for(;holdIndex >= 0;holdIndex --)
__adjust_heap(first, holdIndex, len, *(first+holdIndex));
}
template<class T>
void __pop_heap(T first,T last,T point){
int temp = *first;
*first = *point;
*point = temp;
__make_heap(first,last);
}
template<class T>
void __pop_heap(T first,T last){
int value = *(last - 1);
*(last - 1) = *first;
__adjust_heap(first, first, last-1-first, value);
}
template<class T>
void __sort(T first,T last){
while(last - first > 1)
__pop_heap(first,last--);
}
template<class T>
void _partial_sort(T first,T middle,T last){
__make_heap(first,middle);
for(T i = middle;i != last;i ++)
if(*i < *first)
__pop_heap(first,middle,i);
}
#endif // _HEAP_SORT_H_INCLUDED
文件名:_quick_sort.h
/*
* quick_sort简答实现,递归方法在intro_sort.h中呈现,这里只是根据cut作为标兵,来进行左右的调整
*created by A_Bo
*/
#ifndef _QUICK_SORT_H_INCLUDED
#define _QUICK_SORT_H_INCLUDED
template<class T>
void swap(T a,T b){
T temp = a;
a = b;
b = temp;
}
template<class T>
T __unguarded_partition(T first, T last, T cut){
while(true){
while(*first < *cut) ++first;
--last;
while(*last > *cut) --last;
if(!(first < last)) return first; //first为分割后右段的第一个位置
swap(*first,*last);
++first;
}
}
#endif // _QUICK_SORT_H_INCLUDED
文件名:_intor_sort.h
/*
*introSort算法具体实现
*created by A_Bo
*/
#ifndef _INTRO_SORT_H_INCLUDED
#define _INTRO_SORT_H_INCLUDED
#include "_heap_sort.h"
#include "_quick_sort.h"
#include "_insertion_sort.h"
const int __stl_threshold = 16;
template<class T>
void __introsort_loop(T first, T last,int depth_limit){
while(last - first > __stl_threshold){
if(depth_limit == 0){
_partial_sort(first,last,last); //
return ;
}
depth_limit --;
T cut = __unguarded_partition(first+1,last,first); //使用头位置为标志节点
__introsort_loop(cut,last,depth_limit); //对右段进行递归操作
last = cut;
//递归回来,执行左半段的操作 因为上面的while原因
}
}
int __lg(int len){
int k = 0;
for(;len > 1;len >>= 1) k++;
return k;
}
template<class T>
void _final_insertion_sort(T first,T last){
if(last - first > __stl_threshold){
__insertion_sort(first,first+__stl_threshold);
for(T i = first+__stl_threshold;i != last;i ++)
__unguarded_liner_insert(i,*i);
}
else
__insertion_sort(first,last);
}
template<class T>
inline void sort(T first,T last){
if(first != last){
__introsort_loop(first,last,__lg(last-first)*2);
_final_insertion_sort(first,last);
}
}
#endif // _INTRO_SORT_H_INCLUDED
测试程序:
#include <iostream>
#include "_intro_sort.h"
using namespace std;
int main()
{
int a[] = {9,2,6,4,8,1,0,16,59,12,10,13,45,76,12,13,17}; //17
sort(a, a+17);
for(int i = 0 ;i < 17;i ++)
cout<<a[i]<<" ";
cout<<endl;
}
参考书籍
《STL源码剖析》 侯捷著
时间复杂度参考:https://www.cnblogs.com/gaochundong/p/comparison_sorting_algorithms.html