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


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

一個優化算法理論時間復雜度的實例點這里

另一個實例點這里

時間復雜度\(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\)

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

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桶數組的初始化部分可以強行展開出來並行計算。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM