基數排序模板(基數排序,C++模板)

算法的理論學習可右轉Creeper_LKF大佬的洛穀日報html

一個優化算法理論時間複雜度的實例點這裏c++

另外一個實例點這裏算法

時間複雜度\(O(n)\),算常數的話要乘位長。數組

蒟蒻參考了Creeper_LKF大佬的模板,並在通用性上面稍微提高了一點。能夠兼容全部存儲整數的基本類型,以及在此基礎上構建的結構體類型(多關鍵字排序時,優先級高的關鍵字默認須要在結構體中靠後)。緩存

函數原型函數

template<typename T>
void Radixsort(T*fst,T*lst,T*buf,int*op)

T即爲待排序的類型名,fst lst爲首尾指針(和sort同樣),buf爲緩衝區指針,op爲操做列表。學習

\(op[i]\)提供類型的第\(i\)個字節的比較方式,具體來講有\(5\)種取值。
\(-1\):該字節不是排序的關鍵字。
\(0\):以該字節爲基準從小到大排序。
\(1\):以該字節爲基準從大到小排序。
\(2\):以該字節爲基準從小到大排序,且該字節的最高位是有符號整形的符號位。
\(3\):以該字節爲基準從大到小排序,且該字節的最高位是有符號整形的符號位。優化

例如,對int從小到大排序,則應將\(\{0,0,0,2\}\)傳入\(op\)ui

對結構體unsigned int,int之前一個爲關鍵字從大到小排序,則代碼大體寫成spa

Radixsort(a,a+n,buf,new int[8]{1,1,1,1,-1,-1,-1,-1});

對長度爲\(n\)int數組排序效率對好比下:(STL不吸氧是真的布星)
\[\begin{matrix} 方式&n=10^6,不開\text{O2}&n=5*10^6,不開\text{O2}&n=5*10^6,開\text{O2}&n=10^7,開\text{O2}\\ \text{Radixsort}&\text{20ms}&\text{120ms}&\text{60ms}&\text{120ms}\\ \text{std::sort}&\text{200+ms}&\text{1100+ms}&\text{320+ms}&\text{680+ms}\\ \text{std::stable_sort}&\text{210+ms}&\text{1200+ms}&\text{410+ms}&\text{860+ms} \end{matrix}\]

然而,Radixsort的運行時間與待排序類型的關鍵字位長總和成正比(upd:蒟蒻目測和總位長也有關,猜想是由於訪問步長增長致使緩存刷新次數增長。例如,對long long排序大約是對int排序的三倍時間)。

std::sort受此的影響小多了。當總位長在\(10\)位以上時,開O2之後二者的差距很小了。因此綜合實現難度方面,int多關鍵字和long long等用開O2的std::sort就夠了。

至於實數類型,Radixsort不能直接資磁。double\(8\)位的用std::sort就行了。至於若是是在想從小到大排float的話,必須膜改一下數組,將全部的負實數強行除了符號位都按位取反之後,傳入\(\{0,0,0,2\}\),最後還要還原回來,實在是太麻煩了。

#include<bits/stdc++.h>
#define UC unsigned char
using namespace std;
template<typename T>
void Radixsort(T*fst,T*lst,T*buf,int*op){
    static int b[0x100];
    int Len=lst-fst,Sz=sizeof(T),at=0,i,j;
    UC*bgn,*end,tmp;
    for(i=0;i<Sz;++i){
        if(op[i]==-1)continue;
        bgn=(UC*)fst+i;end=(UC*)lst+i;
        tmp=((op[i]&1)?0xff:0)^((op[i]&2)?0x80:0);
        memset(b,0,sizeof(b));
        for(UC*it=bgn;it!=end;it+=Sz)++b[tmp^*it];
        for(j=1;j<0x100;++j)b[j]+=b[j-1];
        for(UC*it=end;it!=bgn;buf[--b[tmp^*(it-=Sz)]]=*--lst);
        lst=buf+Len;swap(fst,buf);at^=1;
    }
    if(at)memcpy(buf,fst,Sz*Len);
}

有沒有以爲很好實現呢?比什麼後綴排序不知道好寫到哪裏去了

這樣實現很簡短,但常數沒有卡到極限,b桶數組的初始化部分能夠強行展開出來並行計算。

相關文章
相關標籤/搜索