【问题标题】:When does grouping in radix-sort give an advantage?基数排序中的分组何时具有优势?
【发布时间】:2016-11-17 08:50:21
【问题描述】:

我一直在测试this radix-Sort 的实现:

public void RadixSort(int[] a)
{  
// our helper array 
int[] t=new int[a.Length]; 

// number of bits our group will be long 
int r=4; // try to set this also to 2, 8 or 16 to see if it is quicker or not 

// number of bits of a C# int 
int b=32; 

// counting and prefix arrays
// (note dimensions 2^r which is the number of all possible values of a r-bit number) 
int[] count=new int[1<<r]; 
int[] pref=new int[1<<r]; 

// number of groups 
int groups=(int)Math.Ceiling((double)b/(double)r); 

// the mask to identify groups 
int mask = (1<<r)-1; 

// the algorithm: 
for (int c=0, shift=0; c<groups; c++, shift+=r)
{ 
    // reset count array 
    for (int j=0; j<count.Length; j++)
        count[j]=0;

    // counting elements of the c-th group 
    for (int i=0; i<a.Length; i++)
        count[(a[i]>>shift)&mask]++; 

    // calculating prefixes 
    pref[0]=0; 
    for (int i=1; i<count.Length; i++)
        pref[i]=pref[i-1]+count[i-1]; 

    // from a[] to t[] elements ordered by c-th group 
    for (int i=0; i<a.Length; i++)
        t[pref[(a[i]>>shift)&mask]++]=a[i]; 

    // a[]=t[] and start again until the last group 
    t.CopyTo(a,0); 
} 
// a is sorted 
}

而且我不太明白为什么要将 r 设置为与 b 不同的值。 通过始终将其设置为 b 值,我得到了最好的结果。什么是我从使用比 b 更小的值中获得优势的例子?

编辑:这仅在您不使用输入类型的全部范围时才有效: 示例:如果使用 r = b

【问题讨论】:

  • 教科书中的理想情况(不考虑缓存)和这个旧线程中的实际数字:radix sort optimal base
  • @rcgldr 谢谢!正是我想要的。因此,当 b=r 时,我实际上具有最佳 O(2n + 2^r) 运行时间。因此,如果我不需要精确的精度,我可以通过调整 r 和规范化输入来创建具有截止值的“桶”值? (设置 r=b=2 将产生 3 个桶,r=b=3 将产生 7 个等,我可以通过捕获前缀和计数来获取我感兴趣的子集?现在我只需要一个正当的理由来使用它,因为我只是在循环中稍微击败了一个简单的 if/else 来获取我对基数感兴趣的案例:P
  • 即使你有内存,r == b == 32 也不是理想的,除非要排序的数组是> 910亿个元素(估计,我没有简单的方法来验证这一点)在理想化的情况下,并且在考虑缓存问题时更大。整数的 r == b 也可以实现为计数排序。旁注 - 您用于基数排序的代码不处理负整数。
  • 您可以通过使用单次创建计数和前缀来提高基数排序的性能。我在这个C++ example radix sort 中使用了一个矩阵。
  • @rcgldr 我发布的示例仅对 r==b,.. 执行单遍。它的执行速度比快速排序快 10 倍。我的输入不大于 4000,所以我将 r 和 b 设置为 12。但是,我实际上不需要完美的排序。通过仅对 r 和 b 使用 2 位,我可以比 q 排序快 40 倍。然后我没有完美的排序,但是输入被分成 3 组,..对于 inputmax = 4000,第 1 组将是[0,1333[ group 2 ]1333,2666[.. etc.. 用例是避免执行 if/else 并通过返回 group1 来获取 if 组

标签: c# algorithm performance sorting


【解决方案1】:

我不明白使用 2 位将 4000 个元素分成 3 个组,因为 4000 / 3 不是 2 的幂。

如果取值范围为 0 到 4000,且数组大小 >= 4000,则计数排序会更快:

#define SORTMAX 4000
void CountSort(int a[], size_t n)
{
    size_t cnt[SORTMAX + 1];
    for (size_t i = 0; i <= SORTMAX; i++)
        cnt[i] = 0;
    for (size_t i = 0; i < n; i++)
        cnt[a[i]]++;    // no out of range check
    for (size_t j = 0, i = 0; i <= SORTMAX; i++)
        while (cnt[i]--)
            a[j++] = (int)i;
}

【讨论】:

  • 4000/3 = 1333,3。 => 低于 1333,3 的每个值都设置为 0;每个高于或等于 1333,3 和低于 2666,6 的值都设置为 1 ...等等,然后对其进行基数。我不知道 countsort,.. 看起来它只是通过用 while(cnt[i]--) 替换它来节省我的前缀数组?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 2016-01-26
  • 2014-01-04
  • 2022-11-01
  • 1970-01-01
  • 2022-08-16
  • 2015-12-29
相关资源
最近更新 更多