• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            STL 中sort源碼分析

            Posted on 2013-06-01 18:53 鑫龍 閱讀(426) 評論(0)  編輯 收藏 引用 所屬分類: STL

            轉(zhuǎn)自:http://blog.csdn.net/superhackerzhang/article/details/6410670 

            以SGI的STL為例

             

            sort有兩種重載形式

             

            template <class RandomAccessIterator>

            void sort(RandomAccessIterator first, RandomAccessIterator last);  
            template <class RandomAccessIterator, class StrictWeakOrdering>
            void sort(RandomAccessIterator first, RandomAccessIterator last,StrictWeakOrdering comp);
            這兩種形式都要求形隨機訪問迭代器,因此只能用于容器vector或deque,這里我們只以第一種為例進行講解
            在數(shù)據(jù)量大時,采用Quick Sort,分段遞歸排序,一旦分段后的數(shù)據(jù)量小于門限值時,為避免遞歸的額外開銷,便采用Insertion sort。 
            如果遞歸的層次過深,還會使用Heap Sort.
            對于以下的以__開頭的命名函數(shù),表示其為被內(nèi)部的其它函數(shù)調(diào)用,而不能被用戶直接調(diào)用。
            首先來看插入排序
            template <class _RandomAccessIter> 
            void __insertion_sort(_RandomAccessIter __first, _RandomAccessIter __last) {   
            if (__first == __last) return;    
            for (_RandomAccessIter __i = __first + 1; __i != __last; ++__i)     
            __linear_insert(__first, __i, __VALUE_TYPE(__first)); }
            其所調(diào)用的 __linear_insert如下示:
            template <class _RandomAccessIter, class _Tp>
            inline void __linear_insert(_RandomAccessIter __first, 
                                        _RandomAccessIter __last, _Tp*) {
              _Tp __val = *__last;
              if (__val < *__first) {
                copy_backward(__first, __last, __last + 1);
                *__first = __val;
              }else
                __unguarded_linear_insert(__last, __val);
            }
            這里需要對其進行一下說明,通常情況下在進行插入排序時,既要進行大小的比較,又要對邊界進行控制,經(jīng)過上面的改進后,但只需要進行大小的比較便可,這就是代碼的高明這處。
            首先對要插入有序部分的元素__val與隊首的最小元素 *__first進行比較,如果__val < *__first,則只__first與 __last之間的元素向后移一個位置,然后將__val插入隊首。
            如果__val >= *__first,則說明__val在將要新生成的有序隊列中不是最小,因此,在下面的while中不用進行界限控制,只比較元素的大小即可。
            template <class _RandomAccessIter, class _Tp> 
            void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val) {
            _RandomAccessIter __next = __last;
            --__next;
            while (__val < *__next) {
            *__last = *__next;
            __last = __next;
            --__next;
            }
            *__last = __val;
            }
            在STL中對避免快排時每次都選擇最小或最大的元素做軸,使用以下函數(shù)選擇一個三點中值。
            template <class _Tp> 
            inline const _Tp& __median(const _Tp& __a, const _Tp& __b, const _Tp& __c) {
            __STL_REQUIRES(_Tp, _LessThanComparable);
            if (__a < __b)
            if (__b < __c) return __b;
            else if (__a < __c) return __c;
            else return __a;
            else if (__a < __c) return __a;
            else if (__b < __c) return __c;
            else return __b;
            }
            下面是快排中所要使用的分割函數(shù)。對[first,last)區(qū)間的元素進行分割,使用得中軸右邊的元素大于等于中軸,左邊的元素小于等于中軸,并返回中軸所在位置。
            template <class _RandomAccessIter, class _Tp> 
            _RandomAccessIter __unguarded_partition(_RandomAccessIter __first,_RandomAccessIter __last,_Tp __pivot) {
            while (true) {
            while (*__first < __pivot) ++__first;
            --__last;
            while (__pivot < *__last) --__last;
            if (!(__first < __last))
            return __first;
            iter_swap(__first, __last);
            ++__first;
            }
            }
            sort 代碼如下
            template <class _RandomAccessIter> 
            inline void sort(_RandomAccessIter __first, _RandomAccessIter __last) {
            if (__first != __last) {
            __introsort_loop(__first, __last,
            __VALUE_TYPE(__first),
            __lg(__last - __first) * 2);
            __final_insertion_sort(__first, __last);
            }
            }
            基中__lg(n)用來找出2^k<=n的最大k值,用以控控制遞歸的深度。
            template <class _Size> 
            inline _Size __lg(_Size __n) {
            _Size __k;
            for (__k = 0; __n != 1; __n >>= 1) ++__k;
            return __k;
            }
            下面的是用來對區(qū)間使用快排,以達到部分有序狀態(tài)。
            template <class _RandomAccessIter, class _Tp, class _Size> 
            void __introsort_loop(_RandomAccessIter __first,
            _RandomAccessIter __last, _Tp*,
            _Size __depth_limit) {
            while (__last - __first > __stl_threshold) {//__stl_threshold在這里用前面定義的常量16,當區(qū)間多于16個元素時,才有必要使用快排。
            if (__depth_limit == 0) {//當遞歸的層次過深時,使用堆排序。
            partial_sort(__first, __last, __last);
            return;
            }
            --__depth_limit;
            _RandomAccessIter __cut = __unguarded_partition(__first, __last,
            _Tp(__median(*__first,
            *(__first + (__last - __first)/2),
            *(__last - 1))));//使用分割函數(shù),反回中軸
            __introsort_loop(__cut, __last, (_Tp*) 0, __depth_limit);//對右半部分進行遞歸排序
            __last = __cut;//使尾指針指向中軸,即要對左半部分排序
            }
            }
            最后使用插入排序?qū)Ω鞑糠诌M行排序。
            template <class _RandomAccessIter> 
            void __final_insertion_sort(_RandomAccessIter __first,
            _RandomAccessIter __last) {
            if (__last - __first > __stl_threshold) {
            __insertion_sort(__first, __first + __stl_threshold);
            __unguarded_insertion_sort(__first + __stl_threshold, __last);
            } else __insertion_sort(__first, __last);
            }
            些函數(shù)先判斷元素個數(shù)是否大于16,如是大于,則先用__insertion_sort()對16個元素的子序列排序,再用__unguarded_insertion_sort()對
            其余的排序。否則直接用__insertion_sort()排序。
            template <class _RandomAccessIter> 
            inline void __unguarded_insertion_sort(_RandomAccessIter __first,
            _RandomAccessIter __last) {
            __unguarded_insertion_sort_aux(__first, __last, __VALUE_TYPE(__first));
            }

            template <class _RandomAccessIter, class _Tp, class _Compare>
            void __unguarded_insertion_sort_aux(_RandomAccessIter __first,
            _RandomAccessIter __last,
            _Tp*, _Compare __comp) {
            for (_RandomAccessIter __i = __first; __i != __last; ++__i)
            __unguarded_linear_insert(__i, _Tp(*__i), __comp);
            }
            template <class _RandomAccessIter, class _Tp> 
            void __unguarded_linear_insert(_RandomAccessIter __last, _Tp __val) {
            _RandomAccessIter __next = __last;
            --__next;
            while (__val < *__next) {
            *__last = *__next;
            __last = __next;
            --__next;
            }
            *__last = __val;
            }
            ps:個人感覺__final_insertion_sort()中區(qū)分區(qū)間大小是多此一舉,因為最終其調(diào)用的都是__unguarded_linear_insert(),其并沒用針對不
            同的大小區(qū)間采用明顯不用的算法。
            99久久精品影院老鸭窝| 欧美一区二区三区久久综合| 国产精品久久久久久影院| 亚洲伊人久久大香线蕉苏妲己| 丰满少妇人妻久久久久久| 久久99精品久久久久久不卡| 人妻无码精品久久亚瑟影视| 久久不射电影网| 久久久久久久久波多野高潮| 久久久精品免费国产四虎| 久久精品国产亚洲AV香蕉| 久久精品国产72国产精福利| 欧美黑人又粗又大久久久| 亚洲国产日韩欧美久久| 久久美女人爽女人爽| 久久久一本精品99久久精品66| 久久精品国产一区二区三区不卡| 精品国产乱码久久久久久1区2区 | 亚洲国产精品嫩草影院久久| 久久国产精品77777| 久久伊人五月丁香狠狠色| 91精品国产色综久久| 91精品国产91久久综合| 狠狠精品久久久无码中文字幕| 国产精品成人精品久久久| 国产精品久久成人影院| 久久亚洲精品无码AV红樱桃| 亚洲中文字幕久久精品无码APP | 久久久久国产一区二区| 久久―日本道色综合久久| 精品一区二区久久| 久久精品国产亚洲精品2020| 无码国产69精品久久久久网站| 久久午夜无码鲁丝片秋霞| 久久精品日日躁夜夜躁欧美| 午夜福利91久久福利| 久久精品国产精品亚洲精品| 中文字幕久久精品无码| 久久香综合精品久久伊人| 久久久久久久人妻无码中文字幕爆 | 精品久久久久久综合日本|