1. 程式人生 > >C++實現introSort演算法

C++實現introSort演算法

寫在前面

在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