C++實現introSort演算法
阿新 • • 發佈:2018-11-11
寫在前面
在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