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

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/83588180