• 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);

            }

        }


  • 相关阅读:
    jQuery learning
    【转】PHP技巧汇总:提高PHP性能的53个技巧
    [转]浅谈JavaScript编程
    英语常用口语
    中文数字转换为阿拉伯数字
    [ASP.NET MVC 3.0]JsonValueProviderFactory讓Action接收Json更輕鬆
    xapian_binaries
    查询sql数据库中的所有表和表描述
    scrollTop获取不到值的解决方法
    iframe操作ie,firefox兼容
  • 原文地址:https://www.cnblogs.com/boydfd/p/4983150.html
Copyright © 2020-2023  润新知