青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-162  評論-223  文章-30  trackbacks-0
基本原理
   數據輸入隨機分布的情況下,快速排序具有較好的性能表現,但當元素個數比其關鍵字的取值范圍大,而這個范圍相對較小時,使用一種關鍵字索引統計排序會快很多,因為它的時間復雜度是線性的,基本原理是使用數組(為描述方便,特稱統計數組),其下標對應關鍵字的值,存儲元素按待排序關鍵字的值統計的出現次數,然后再按元素關鍵字的值,結合統計數組,放回到最終位置上。常規的實現是使用一個輔助空間來有序存儲原來的所有元素,再從輔助空間拷貝到原空間,而這個輔助空間大小至少和原空間一樣大,因此這種實現很耗內存,它的好處在于算法是穩定的。為了減少內存占用和拷貝開銷,進一步提高性能,本文講述一種改進的方案,僅在原空間上移動數據就能達到排序效果,但犧牲了穩定性。為方便下文的討論描述,設關鍵字取值范圍為KeyRange,值域是閉區間[min,max],min為最小值,max為最大值,統計數組為CntArray。顯然,這里關鍵字的類型是整型,在標準c/c++中,整型至少有char,unsigned char,short,unsigned short,int,unsigned int,long,unsigned long 8種,對于有符號整型,KeyRange中的min和(或)max會取負值,所以要映射到CntArray的下標0到max-min之間。

設計實現
   在算法設計封裝上,為了支持在編譯期或運行期給出關鍵字min和max的值,每種元素類型的實現有兩種函數版本:對于運行期版本,考慮到當min和max的實際取值在較小的范圍內,統計數組可以在棧而不是堆上分配,這樣有助于一定的性能提升,因而使用了boost中的auto_buffer組件,為方便靈活配置auto_buffer的內部靜態空間大小,因此在函數外部提供了接口以輸入這個閾值(常量模板參數);對于編譯期版本,為了代碼重用,內部則是調用對應的運行期版本來實現的。關于統計數組的運用,其個數和空間大小則取決于因元素類型而不同的實現,這里元素類型分為三種:基本整型、類類型和指針類型,下面就這三種類型分別詳述對應的算法實現。

   實現算法的函數名稱為statistic_sort,對于不同的元素類型,函數所帶的參數不同,類類型和指針類型比基本整型多了一個獲取關鍵字方法的參數,這里的參數包括模板類型形參和函數調用形參,其內部實現則調用了輔助函數__init_index_array__aux_index_sort。
   1)基本整型:在這種情況下,元素本身就是關鍵字,CntArray每項存儲的是下標值對應的元素出現的次數,空間大小是max-min+1,對應的運行期版本實現如下 
 1template<class _KeyT,class _RandIt>
 2void __init_index_array(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max,size_t* cnt)
 3{
 4    assert(_min <= _max);
 5    std::fill_n(cnt,_max-_min+1,0);
 6}

 7
 8template<class _KeyT,class _RandIt>
 9void __aux_index_sort(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max,size_t* cnt)
10{
11    typedef typename std::iterator_traits<_RandIt>::value_type value_type;
12    BOOST_STATIC_ASSERT((boost::is_same<_KeyT,value_type>::value));
13
14    for (_RandIt it = _first; it != _last; ++it)
15    {
16        assert(_min <= *it && *it <= _max);
17        ++cnt[*it-_min];
18    }

19    for (size_t i = 0,j = 0; i < _max - _min + 1++i)
20    {
21        while(cnt[i]--)    *(_first + (j++)) = i + _min;
22    }

23}

24
25template<class _KeyT,size_t N,class _RandIt>
26void statistic_sort(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max)
27{
28    using namespace boost::signals2::detail;
29    auto_buffer<size_t,store_n_objects<N> > cnt(_max-_min+1);
30
31    __init_index_array<_KeyT>(_first,_last,_min,_max,cnt.data());
32    __aux_index_sort<_KeyT>(_first,_last,_min,_max,cnt.data());
33}
   編譯期版本如下 
 1template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt>
 2inline void __init_index_array(_RandIt _first,_RandIt _last,size_t* cnt)
 3{
 4    BOOST_STATIC_ASSERT(_min<=_max);
 5    __init_index_array(_first,_last,_min,_max,cnt);
 6}

 7
 8template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt>
 9void __aux_index_sort(_RandIt _first,_RandIt _last,size_t* cnt)
10{
11    BOOST_STATIC_ASSERT(_min<=_max);
12    __aux_index_sort(_first,_last,_min,_max,cnt);
13}

14
15template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt>
16void statistic_sort(_RandIt _first,_RandIt _last)
17{
18    size_t cnt[_max-_min+1];
19
20    __init_index_array<_KeyT,_min,_max>(_first,_last,cnt);
21    __aux_index_sort<_KeyT,_min,_max>(_first,_last,cnt);
22}
   從上面可看出,有兩處使用了BOOST_STATIC_ASSERT宏在編譯期檢測減免不必要的錯誤,一是診斷關鍵字的取值范圍是否合理,二是診斷迭代器指向的元素和關鍵字類型是否相同,這一技術在下面的代碼中也多次用到。
   2)類類型:在這種情況下,用到了兩個CntArray,一個是起始數組Beg,空間大小為max-min+2(其實下標max-min+1用不上),每項存儲的是比對應關鍵字小的所有元素出現的次數,也就是關鍵字在序列中的起始索引;另一個是結束數組End,每項存儲的是對應關鍵字的結束索引。這兩個數組用來判斷元素是否處于最終正確的位置上,如果是,那么就不移動元素,否則,要移動元素到End指示的位置上,在移動前,為防止覆蓋目標位置上的元素,需臨時保存目標位置處的元素和該元素對應的目標位置,繼續這個過程,直到目標位置等于當前位置時停止。不同于基本整型,元素的關鍵字是元素的內部成員,需要通過一種方法來獲取,而這種方法可以是自由普通函數,也可以是類的成員函數,還可以是函數對象,只要最終能滿足調用規則即可,這個調用規則是返回關鍵字類型,帶1個類型為元素常量引用的參數。對應的運行期版本實現如下    
 1template<class _KeyT,class _RandIt,class _Func>
 2void __init_index_array(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max,size_t* cnt_beg,size_t* cnt_end,_Func _getKey)
 3{
 4    typedef typename std::iterator_traits<_RandIt>::value_type value_type;
 5
 6    typedef typename boost::remove_pointer<_Func>::type F;
 7    typedef typename boost::function_traits<F>::result_type result_type;
 8    typedef typename boost::function_traits<F>::arg1_type arg_type;
 9    typedef typename boost::add_const<value_type>::type const_type;
10    typedef typename boost::add_reference<const_type>::type const_reference;
11
12    BOOST_STATIC_ASSERT((boost::is_same<result_type,_KeyT>::value));
13    BOOST_STATIC_ASSERT((boost::is_same<arg_type,const_reference>::value));
14
15    size_t N = _max - _min + 1;
16    std::fill_n(cnt_beg,N + 1,0);
17
18    for (_RandIt it = _first; it != _last; ++it)
19    {
20        assert(_min <= _getKey(*it) && _getKey(*it) <= _max);
21        ++cnt_beg[_getKey(*it) - _min + 1];
22    }

23    for (size_t i = 1;i < N;++i)
24    {
25        cnt_beg[i] += cnt_beg[i - 1];
26    }

27    std::copy(cnt_beg,cnt_beg + N,cnt_end);
28}

29
30template<class _KeyT,class _RandIt,class _Func>
31void __aux_index_sort(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max,size_t* cnt_beg,size_t* cnt_end,_Func _getKey)
32{
33    typedef typename std::iterator_traits<_RandIt>::value_type value_type;
34
35    typedef typename boost::remove_pointer<_Func>::type F;
36    typedef typename boost::function_traits<F>::result_type result_type;
37    typedef typename boost::function_traits<F>::arg1_type arg_type;
38    typedef typename boost::add_const<value_type>::type const_type;
39    typedef typename boost::add_reference<const_type>::type const_reference;
40
41    BOOST_STATIC_ASSERT((boost::is_same<result_type,_KeyT>::value));
42    BOOST_STATIC_ASSERT((boost::is_same<arg_type,const_reference>::value));
43
44    size_t  beg,end,pos,k;
45    value_type val,tmp_val;
46    _KeyT key,tmp_key;
47
48    for (_RandIt it = _first; it != _last; ++it)
49    {
50        val = *it;     key = _getKey(val);
51        assert(_min <= key && key <= _max);
52
53        beg = cnt_beg[key-_min],end = cnt_end[key-_min],pos = std::distance(_first,it);
54        if (pos < beg)
55        {
56            for (k = end; k != pos; k = cnt_end[tmp_key-_min],val = tmp_val)
57            {
58                tmp_val = *(_first + k); tmp_key = _getKey(tmp_val);
59                *(_first + k) = val; ++cnt_end[_getKey(val)-_min];
60            }

61            *(_first + k) = val; ++cnt_end[_getKey(val)-_min];
62        }

63        else if (pos == end)
64        {
65            ++cnt_end[key-_min];
66        }

67        else if (pos > end)
68            assert(false);
69    }

70}

71
72template<class _KeyT,size_t N,class _RandIt,class _Func>
73void statistic_sort(_RandIt _first,_RandIt _last,_KeyT _min,_KeyT _max,_Func _getKey)
74{
75    size_t len = _max - _min + 1;
76    using namespace boost::signals2::detail;
77    auto_buffer<size_t,store_n_objects<N> > cnt_beg(len + 1),cnt_end(len);
78
79    __init_index_array(_first,_last,_min,_max,cnt_beg.data(),cnt_end.data(),_getKey);
80    __aux_index_sort(_first,_last,_min,_max,cnt_beg.data(),cnt_end.data(),_getKey);
81}
   以上代碼有兩處用到了boost中的function_traits,一是來獲取_getKey的返回類型,二是來獲取_getKey的參數類型,并用BOOST_STATIC_ASSERT來診斷它們是否和預期的類型相同。由于function_traits尚不支持函數對象,為了支持使用類的成員函數這一方式來獲取元素關鍵字,所以這里對它進行了特化,代碼如下
 1namespace boost
 2{
 3    template<class _Result,class _Ty>
 4    struct function_traits<std::const_mem_fun_ref_t<_Result,_Ty> > 
 5    {
 6        typedef _Result result_type;
 7        typedef _Ty const& arg1_type;
 8    }
;
 9    template<class _Result,class _Ty>
10    struct function_traits<std::const_mem_fun_t<_Result,_Ty> > 
11    {
12        typedef _Result result_type;
13        typedef _Ty* const& arg1_type;
14    }
;
15}
   編譯期版本實現如下
 1template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt,class _Func>
 2void __init_index_array(_RandIt _first,_RandIt _last,size_t* cnt_beg,size_t* cnt_end,_Func _getKey)
 3{
 4    BOOST_STATIC_ASSERT(_min <= _max);
 5    __init_index_array(_first,_last,_min,_max,cnt_beg,cnt_end,_getKey);
 6}

 7
 8template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt,class _Func>
 9void __aux_index_sort(_RandIt _first,_RandIt _last, size_t* cnt_beg,size_t* cnt_end,_Func _getKey)
10{
11    BOOST_STATIC_ASSERT(_min <= _max);
12    __aux_index_sort(_first,_last,_min,_max,cnt_beg,cnt_end,_getKey);
13}

14
15template<class _KeyT,_KeyT _min,_KeyT _max,class _RandIt,class _Func>
16void statistic_sort(_RandIt _first,_RandIt _last,_Func _getKey)
17{
18    size_t cnt_beg[_max - _min + 2], cnt_end[_max - _min + 1];
19
20    __init_index_array<_KeyT,_min,_max>(_first,_last,cnt_beg,cnt_end,_getKey);
21    __aux_index_sort<_KeyT,_min,_max>(_first,_last,cnt_beg,cnt_end,_getKey);
22}
   3)指針類型:包括基本整型和類類型指針,指針指向真正的元素,在這種情況下,其實現和類類型一樣,只是獲取關鍵字函數的參數類型為指針常量引用而已。
  從以上全部實現可以看出,算法并沒有限制關鍵字的取值范圍,而是由_min和_max決定,也就是說所謂的特定小范圍依賴于實際應用,而這個范圍的上限,理論上則取決于數組空間可支持的最大大小,只不過當范圍相對元素個數較小時,具有良好的性能。

應用示例

 1//自定義類型
 2struct Item
 3{
 4    int key;
 5    int other;
 6
 7    int GetKey() const
 8    {
 9        return key;
10    }

11}
;
12//自由普通函數定義
13inline int GetObjKey(Item const& item)
14{
15    return item.key;
16}

17inline int GetPtrKey(Item* const& item)
18{
19    return item->key;
20}

21
22//支持數組,元素類型為int
23int p[100000];
24//在編譯期指定關鍵字范圍
25statistic_sort<int,-32768,32767>(p,p+sizeof(p)/sizeof(p[0]));
26//在運行期指定關鍵字范圍
27statistic_sort<int,65536>(p,p+sizeof(p)/sizeof(p[0]),-32768,32767);
28
29//支持容器
30//元素類型為Item*,成員函數獲取關鍵字,在運行期指定關鍵字范圍
31vector<Item*> v1;
32statistic_sort<int,65536>(v1.begin(),v1.end(),-32768,32767,std::mem_fun(&Item::GetKey));
33
34//元素類型為Item,成員函數獲取關鍵字,在編譯期指定關鍵字范圍
35vector<Item> v2;
36statistic_sort<int,-32768,32767>(v2.begin(),v2.end(),std::mem_fun_ref(&Item::GetKey));
37
38//自由普通函數獲取關鍵字
39//元素類型為Item,在運行期指定關鍵字范圍
40vector<Item> v3;
41statistic_sort<int,65536>(v3.begin(),v3.end(),-32768,32767,GetObjKey);
42//元素類型為Item*,在編譯期指定關鍵字范圍
43vector<Item*> v4;
44statistic_sort<int,-32768,32767>(v4.begin(),v4.end(),GetPtrKey);
   以上所有代碼在vc2008和gcc4.6下編譯通過,測試結果表明:
   ● 當元素類型為基本整型,且個數大于關鍵字取值范圍較多時,statistic_sort比stl::sort快很多倍,用數組存儲元素的比容器快。
   ● 當元素類型為類類型和指針類型時,性能還取決于獲取關鍵字方法的實現,當機器直接支持高效獲取關鍵字時(如位運算),則比快速排序要快,而用自由普通函數方式獲取關鍵字的比類成員函數要快。
   ● 所有編譯期版本比運行期要快。
posted on 2012-05-31 12:11 春秋十二月 閱讀(1816) 評論(0)  編輯 收藏 引用 所屬分類: Algorithm
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品一区二区三区成人| 欧美三级视频在线观看| 国产一本一道久久香蕉| 欧美一级大片在线观看| 性做久久久久久久久| 国产精自产拍久久久久久蜜| 久久久97精品| 老色鬼久久亚洲一区二区| 亚洲电影免费观看高清| 亚洲激情国产| 欧美日韩一区二区免费视频| 羞羞视频在线观看欧美| 欧美影院成人| 亚洲伦理一区| 午夜精品免费视频| 亚洲电影中文字幕| 在线亚洲观看| 在线看无码的免费网站| 日韩午夜激情av| 国产午夜精品一区二区三区欧美| 美女诱惑一区| 国产精品劲爆视频| 美女视频黄a大片欧美| 欧美日韩久久| 久色成人在线| 国产精品jizz在线观看美国 | 亚洲激情欧美| 日韩视频免费观看高清完整版| 国产精自产拍久久久久久| 欧美国产日本高清在线| 国产精品综合色区在线观看| 亚洲国产婷婷香蕉久久久久久99 | 中文久久乱码一区二区| 久久高清一区| 亚洲中字黄色| 欧美精品一区二区三区一线天视频| 亚洲欧美日韩一区二区在线| 欧美xxx成人| 久久久999精品视频| 欧美视频免费看| 亚洲高清资源| 欲色影视综合吧| 亚洲在线免费| 亚洲视频在线观看视频| 蜜臀a∨国产成人精品| 欧美在线免费观看| 欧美日韩精品久久| 亚洲第一页在线| 一区二区亚洲精品| 先锋影音久久| 亚洲欧美日韩精品一区二区| 欧美精品自拍| 亚洲激情电影中文字幕| 亚洲欧洲三级| 免费观看成人鲁鲁鲁鲁鲁视频| 久久裸体视频| 国产一区在线免费观看| 亚洲女人小视频在线观看| 亚洲网址在线| 欧美日韩一区二区三区在线观看免| 亚洲国产精品久久久久秋霞蜜臀| 亚洲国产精品一区二区第一页| 欧美制服丝袜| 久久精品一区二区三区不卡| 国产亚洲精品久久久久动| 亚洲天天影视| 午夜日韩视频| 国产亚洲毛片在线| 欧美亚洲网站| 美女亚洲精品| 亚洲黄色尤物视频| 欧美激情精品久久久久久蜜臀| 亚洲激情视频| 亚洲一二三区视频在线观看| 国产精品爽爽ⅴa在线观看| 亚洲综合久久久久| 久久精品亚洲| 亚洲高清视频一区二区| 免费日韩成人| 日韩一级在线观看| 午夜在线一区二区| 国产一区二区主播在线| 久久综合久久综合这里只有精品| 欧美激情网站在线观看| aaa亚洲精品一二三区| 国产精品大全| 久久国产日韩| 亚洲国产日韩欧美在线动漫| 亚洲一区免费| 国产综合久久久久影院| 欧美成人视屏| 中文精品一区二区三区| 久久久久99精品国产片| 亚洲激情国产| 国产精品久久久久久久久久尿| 欧美一区二区三区久久精品| 欧美黄在线观看| 一本色道久久综合亚洲精品不卡| 国产精品区二区三区日本| 欧美一区二区三区在线观看| 美女国产精品| 亚洲主播在线观看| 在线观看亚洲精品视频| 欧美午夜欧美| 久久资源av| 亚洲香蕉视频| 欧美激情五月| 一区二区三区高清在线观看| 国产精品普通话对白| 免费观看一级特黄欧美大片| 亚洲欧美日韩综合国产aⅴ| 欧美国产三区| 久久久www成人免费无遮挡大片| 亚洲免费观看高清完整版在线观看熊| 欧美日韩国产高清| 久久综合给合久久狠狠色| 亚洲国产日韩欧美综合久久| 欧美在线免费观看视频| 亚洲视频中文| 亚洲欧洲一级| 激情综合网址| 国产精品vvv| 免费成人在线视频网站| 欧美一级二区| 亚洲午夜精品国产| 亚洲另类春色国产| 免费影视亚洲| 久久精品伊人| 欧美一级一区| 亚洲欧美日韩综合一区| 日韩午夜电影av| 亚洲国产精品一区二区久| 国产视频欧美视频| 国产精品久久国产三级国电话系列 | 999亚洲国产精| 亚洲国产精品尤物yw在线观看| 国产亚洲精品资源在线26u| 欧美日韩99| 欧美精品一区二区在线观看| 开元免费观看欧美电视剧网站| 欧美一区二区福利在线| 亚洲欧美日韩视频二区| 亚洲一区二区三区精品在线| 在线视频精品一区| 一本色道久久综合精品竹菊 | 久久久噜噜噜久久| 久久久欧美精品sm网站| 久久亚洲综合网| 久久先锋影音av| 免费成人小视频| 麻豆精品网站| 欧美激情网站在线观看| 亚洲国产精品一区二区第一页| 亚洲国产成人精品久久久国产成人一区| 欧美成va人片在线观看| 亚洲国产精品一区二区尤物区| 亚洲欧洲一区二区天堂久久| 亚洲激情欧美激情| 在线视频免费在线观看一区二区| 亚洲午夜久久久| 午夜精品免费在线| 久久久亚洲综合| 蜜桃精品一区二区三区 | 欧美一区二区三区啪啪 | 亚洲精品在线三区| 一区二区冒白浆视频| 亚洲欧美一区二区视频| 久久久久九九九| 美日韩精品免费观看视频| 欧美日韩成人激情| 国产精品永久| 亚洲国产日韩在线| 亚洲与欧洲av电影| 久久久之久亚州精品露出| 亚洲国产精品一区二区www| 夜夜爽www精品| 久久久人成影片一区二区三区观看| 欧美激情精品久久久| 国产日韩在线一区二区三区| 亚洲日韩欧美视频| 欧美一区二区三区免费大片| 欧美福利影院| 亚洲欧美在线免费观看| 欧美 日韩 国产 一区| 国产精品亚洲精品| 亚洲激情自拍| 久久精品亚洲一区| 亚洲三级视频在线观看| 久久不射2019中文字幕| 欧美深夜影院| 亚洲国产裸拍裸体视频在线观看乱了中文 | 欧美日韩在线免费| 国内精品视频一区| 亚洲性图久久| 亚洲黄一区二区| 久久成人精品无人区| 国产精品福利久久久| 亚洲精品欧美日韩专区| 久久久久久亚洲精品中文字幕| 一区二区日本视频|