我有一個小問題,找不到滿意的解決方案。 有一個字節數組,我需要這些字節按高7位排序,而 保留低位的順序。快速排序的字節數組
所以最初它看起來是這樣的:
// sort buf[N] to tmp[N]
uint offs[128+1]; uint c,i,s;
for(i=0; i<128; i++) offs[i]=0;
for(i=0; i<l; i++) offs[buf[i]>>1]++;
for(i=0,s=0; i<128; i++) c=offs[i], offs[i]=s, s+=c; offs[i]=s;
byte* tmp = new byte[N];
for(i=0; i<N; i++) c=buf[i], tmp[offs[c>>1]++]=c; // sort
但這些塊是足夠大(目前8M),我想用多線程, 和每個線程的額外8M是明顯的。
所以我試圖用一些簡單的基數排序:
void radix(byte* buf, uint h, uint l, uint mask) {
uint p = (h+l)>>1, q = h;
uint i = offs[h], j = offs[l]-1; h = offs[p];
if((i<h) && (j>=h)) {
byte c = buf[i], d = buf[j];
while((i<h) && (j>=h)) {
while((c&mask)==0) c = buf[++i]; // find value with bit 1
while((d&mask)!=0) d = buf[--j]; // find value with bit 0
buf[i]=d; buf[j]=c; // swap 1-0 -> 0-1
c = buf[++i]; d = buf[--j];
}
if(mask>=4) {
radix(buf, q,p, mask>>1);
radix(buf, p,l, mask>>1);
}
}
}
但它改變了這些低位的順序,它變得不可用。
其實一些簡單的方法,像bubblesort,只是做我想要的,但它們慢得多,速度也是一個問題。
所以目前我排序經由臨時緩衝區更小的塊,然後使用 索引表來訪問,以便部分地排序的塊:
struct tmpsort {
enum{ blocksize = (1<<16)-1 };
unsigned short ofs[(max_quants+blocksize-1)/blocksize][probN];
tmpsort(byte* buf, uint f_len) {
uint i,j,k;
uint freq[2*probN]; // prob freqs
byte tmp[blocksize+1];
for(k=0,j=0; k<f_len; k+=blocksize,j++) {
uint l = Min(k+blocksize,f_len)-k;
byte* p = &buf[k];
// compute offsets of sorted chunks
for(i=0; i<2*probN; i++) freq[i]=0;
for(i=0; i<l; i++) freq[p[i]]++;
for(i=0; i<probN; i++) freq[i+1]=freq[2*i+0]+freq[2*i+1]; // 1=0+1, 2=2+3, 3=4+5
freq[0] = 0;
for(i=0; i<probN; i++) freq[i+1]+=freq[i];
for(i=0; i<probN; i++) ofs[j][i]=freq[i+1];
// sort the block via tmp
for(i=0; i<l; i++) { byte c=p[i]; tmp[freq[c>>1]++]=c; }
for(i=0; i<l; i++) p[i]=tmp[i];
}
}
};
[...]
tmpsort ts(buf, f_len);
for(i=0; i<probN; i++) {
for(k=0,j=0; k<f_len; k+=ts.blocksize,j++) {
uint x = i>0 ? ts.ofs[j][i-1] : 0;
for(; x<ts.ofs[j][i]; x++) putc(buf[k+x],g);
}
}
但是TMP []和OFS []陣列使用太多堆棧空間,它的 不是一個完整的排序,所以我一直想知道是否有一些整潔的解決方案。
數據和我實現的一個樣本在這裏可供選擇: http://nishi.dreamhosters.com/u/tmpsort_v0.rar
謝謝,我真的錯過了這個方法,可能值得嘗試。 – Shelwien 2010-11-17 21:56:40