c - 快速就地排序字节数组

标签 c algorithm sorting

我遇到了一个小问题,找不到满意的解决方案。 有一个字节数组,我需要这些字节按高 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

但是这些 block 足够大(目前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,按我的意思做就行了, 但它们要慢得多,而且速度也是一个问题。

所以目前我通过临时缓冲区对较小的 block 进行排序,然后使用 按顺序访问部分排序的 block 的索引表:

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

最佳答案

为什么不就地使用任何标准,稳定 sorting algorithm ,例如Insertion Sort , 并实现适当的比较器功能 ?

关于c - 快速就地排序字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4204378/

相关文章:

objective-c - 当 float 不为零时,则将其视为零

c++ - 如何在 C 中反转以下算法

java - 在java中翻转标志的计数器

Python - 递归日期排序算法

performance - 使两个直方图成比例的算法,最小化了删除的单位

C - strtok(...) 上的意外段错误

c - 为什么要用一个变量的地址来乘以另一个变量?

C: nftw() 的奇怪行为

algorithm - 如果它们需要 O(n) 时间对列表进行排序,为什么我们不使用尝试进行排序?

ORDER BY 在结构上的 C++ 实现