stl源码剖析 详细学习笔记 算法(5)

//---------------------------15/04/01----------------------------

    //inplace_merge(要求有序)

    template<class BidirectionalIterator>

    inline void inplace_merge(BidirectionalIterator first,

                              BidirectionalIterator middle,

                              BidirectionalIterator last)

    {

        if(first == middle || middle == last)

            return;

        __inplace_merge_aux(first, middle, last, value_type(first),

                            distance_type(first));

    }

    

    template<class BidirectionalIterator, class T, class Distance>

    inline void __inplace_merge_aux(BidirectionalIterator first,

                                    BidirectionalIterator middle,

                                    BidirectionalIterator last,

                                    T*, Distance*)

    {

        Distance len1 = 0;

        distance(first, middle, len1);

        Distance len2 = 0;

        distance(middle, last, len2);

        

        //用来申请暂时的缓冲区

        temporary_buffer<BidirectionalIterator, T> buf(first, last);

        if(buf.begin() == 0)

            __merge_without_buffer(first, middle, last, len1, len2);

        else

            __merge_adaptive(first, middle, last, len1, len2,

                             buf.begin(), Distance(buf.size()));

    }

    

    //有缓冲区的情况

    template<class BidirectionalIterator, class Distance, class Pointer>

    void __merge_adaptive(BidirectionalIterator first,

                          BidirectionalIterator middle,

                          BidirectionalIterator last,

                          Distance len1, Distance len2,

                          Pointer buffer, Distance buffer_size)

    {

        if(len1 <= len2 && len1 <= buffer_size)

        {

            //先复制[first,middle)区间的元素到缓冲区

            Pointer end_buffer = copy(first, middle, buffer);

            //调用merge函数,把元素放入first开始的区间,也就是firstlast

            merge(buffer, end_buffer, middle, last, first);

        }

        else if(len2 <= buffer_size)

        {

            Pointer end_buffer = copy(middle, last, buffer);

            //从后面开始merge

            __merge_backward(first, middle, buffer, end_buffer, last);

        }

        else

        {

            //缓冲区放不下len1 len2,需要进行裁剪

            //搞不懂为什么前面是lower_bound,后面是upper_bound

            //有一种可能是:len1 > len2时,取lower_bound可以使更少的元素换到左边的区间

            //len1 < len2时,取upper_bound可以时更少的元素换到右边。

            //这么做可以平衡两个区间的元素量

            BidirectionalIterator first_cut =first;

            BidirectionalIterator second_cut = middle;

            Distance len11 = 0;

            Distance len22 = 0;

            if(len1 > len2)

            {

                len11 = len1 / 2;

                advance(first_cut, len11);

                second_cut = lower_bound(middle, last, *first_cut);

                distance(middle, second_cut, len22);

            }

            else

            {

                len22 = len2 / 2;

                advance(second_cut, len22);

                first_cut = upper_bound(first, middle, *second_cut);

                distance(first, first_cut, len11);

            }

            //到这时区间是这样的 first      first_cut        middle        second_cut      last

            //为了让为了merge必须让要merge的区间并起来  所以把middlesecond_cut,换到first_cut的位置就可以了

            //rotate first      first_cut(middle)        new_middle(first_cut)

            //          second_cut(second_cut)      last

            BidirectionalIterator new_middle =

                __rotate_adaptive(first_cut, middle, second_cut, len1 - len11,

                                  len22, buffer, buffer_size);

            __merge_adaptive(first, first_cut, new_middle, len11, len22, buffer,

                             buffer_size);

            __merge_adaptive(new_middle, second_cut, last, len1 -len11,

                             len2 - len22, buffer, buffer_size);

        }

    }

    template<class BidirectionalIterator1, class BidirectionalIterator2,

            class Distance>

    BidirectionalIterator __rotate_adaptive(BidirectionalIterator1 first,

                                            BidirectionalIterator1 middle,

                                            BidirectionalIterator1 last,

                                            Distance len1, Distance len2,

                                            BidirectionalIterator2 buffer,

                                            Distance buffer_size)

    {

        //缓冲区足够 就利用缓冲区翻转,不够就调用全局rotate

        BidirectionalIterator2 buffer_end;

        if(len1 > len2 && len2 <= buffer_size)

        {

            buffer_end = copy(middle, last, buffer);

            copy_backward(first, middle, last);

            return copy(buffer, buffer_end, first);

        }

        else if(len1 <= buffer_size)

        {

            buffer_end = copy(first, middle, buffer);

            copy(middle, last, first);

            return copy_backward(buffer, buffer_end, last);

        }

        else

        {

            rotate(first, middle, last);

            advance(first, len2);

            return first;

        }

        

    }

    

    //nth_element

    //使的nth的元素处在完全排序后的位置,只能保证这一个元素处在对的位置

    template<class RandomAccessIterator>

    inline void nth_element(RandomAccessIterator first,

                            RandomAccessIterator nth,

                            RandomAccessIterator last)

    {

        __nth_element(first, nth, last, value_type(first));

    }

    

    template<class RandomAccessIterator, class T>

    void __nth_element(RandomAccessIterator first,

                       RandomAccessIterator nth,

                       RandomAccessIterator last, T*)

    {

        while (last - first > 3)

        {

            //划分一次

            RandomAccessIterator cut = __unguarded_partition

                (first, last, T(__median(*first,

                                         *(first + (last - first) / 2),

                                         *(last - 1))));

            //nth处在哪边就继续划分那边

            if(cut <= nth)

                first = cut;

            else

                last = cut;

        }

        __insertion_sort(first, last);

    }

    

    

    //merge sort

    template<class BidirectionalIterator>

    void mergesort(BidirectionalIterator first, BidirectionalIterator last)

    {

        typename iterator_traits<BidirectionalIterator>::difference_type n

        =distance(first, last);

        if(n == 0 || n == 1)

            return;

        else

        {

            BidirectionalIterator mid = first + n / 2;

            mergesort(first, mid);

            mergesort(mid, last);

            inplace_merge(first, mid, last);

        }

    }


原文地址:https://www.cnblogs.com/boydfd/p/4983150.html