简体   繁体   English

为什么我的基数排序 JAVA 实现比快速排序慢?

[英]Why is my Radix Sort JAVA implementation slower than Quick sort?

I'm trying to write radix code using ByteBuffer.allocate()我正在尝试使用 ByteBuffer.allocate() 编写基数代码
I've learnt that radix sort's time complexity is O(kn) and I wrote this code to make k=4.我了解到基数排序的时间复杂度为 O(kn),我编写了这段代码以使 k=4。
I also wrote quick sort and figured out my radix sort is 2~3 times slower than quick sort.我还写了快速排序,发现我的基数排序比快速排序慢 2~3 倍。
Is it because of inefficient memory access?是因为memory访问效率低吗?
Here's my radix sort code.这是我的基数排序代码。

private static int[] radixSort(int[] value)
{

    byte[][] valueByBytes = new byte[value.length][4];
    for (int i=0; i<value.length; i++) {
        valueByBytes[i] = ByteBuffer.allocate(4).putInt(value[i]).array();
    }

    for (int key = 3; key >=0; key--) {
        valueByBytes = countingSort(valueByBytes, key);
    }

    for (int i=0; i<value.length; i++) {
        value[i] = ByteBuffer.wrap(valueByBytes[i]).getInt();
    }
    return (value);
}

private static byte[][] countingSort(byte[][] valueByBytes, int key) {
    int[] countingArr = new int[256]; // 0 ~ 255
    byte[][] toReturnArr = new byte[valueByBytes.length][4];
    for (int i=0; i<256; i++) {
        countingArr[i] = 0;
    }

    int[] intArr = new int[valueByBytes.length];

    if (key > 0) {
        for (int j=0; j<valueByBytes.length; j++) {
            intArr[j] = (int) valueByBytes[j][key] >= 0 ? valueByBytes[j][key] : 256+valueByBytes[j][key];
        }
    }
    else {
        for (int j=0; j<valueByBytes.length; j++) {
            intArr[j] = (int) valueByBytes[j][key] + 128;
        }
    }

    for (int j=0; j<intArr.length; j++) {
        countingArr[intArr[j]]++;
    }

    for (int i=1; i<256; i++) {
        countingArr[i] = countingArr[i-1] + countingArr[i];
    }

    for (int j=intArr.length-1; j>=0; j--) {
        toReturnArr[countingArr[intArr[j]]-1] = valueByBytes[j];
        countingArr[intArr[j]]--;
    }

    return toReturnArr;
}

Radix sort takes O(x k n) time.基数排序需要 O(x k n) 时间。 Where K is number of digits.其中 K 是位数。 Quick sort takes O(y n log n) where x > y, extracting bits out of a longer key is may be an expensive operation.快速排序需要 O(y n log n) 其中 x > y,从较长的键中提取位可能是一项昂贵的操作。 Overheads used here may be causing trouble in your case.此处使用的开销可能会给您的情况带来麻烦。

You can get more answers by referring this question When should we use Radix sort?您可以通过参考这个问题获得更多答案我们什么时候应该使用基数排序?

Using ByteBuffer along with all the copy|convert operations is slowing down the radix sort.将 ByteBuffer 与所有复制 | 转换操作一起使用会减慢基数排序。 I tested sorting 16777216 integers, and on my system, (Intel 3770K, Windows 7 Pro 64 bit, Netbeans 8.2), the question's radix sort takes about 16.7 seconds, while the implementation of radix sort shown below takes about 0.55 seconds (about 30 times faster), while the implementation of quicksort shown below takes about 1.8 seconds.我测试了对 16777216 个整数进行排序,在我的系统上,(Intel 3770K,Windows 7 Pro 64 位,Netbeans 8.2),问题的基数排序大约需要 16.7 秒,而执行基数排序大约需要 0.5 次,如下所示更快),而下面显示的快速排序的实现大约需要 1.8 秒。

package x;
import java.util.Random;

public class x {

    public static void RadixSort(int[] a)
    {
        int count = a.length;
        if(count < 2)
            return;
        int[] b = new int[count];           // allocate working array
        int [][] mIndex = new int[4][256];  // histograms | indexes
        int i,j,m,n,u;
        for(i = 0; i < count; i++){         // generate histograms
            u = a[i];
            mIndex[0][u&0xff]++;
            u >>= 8;
            mIndex[1][u&0xff]++;
            u >>= 8;
            mIndex[2][u&0xff]++;
            u >>= 8;
            mIndex[3][u+128]++;
        }
        for(j = 0; j < 4; j++){             // convert to indices
            m = 0;
            for(i = 0; i < 256; i++){
                n = mIndex[j][i];
                mIndex[j][i] = m;
                m += n;
            }       
        }
        for(i = 0; i < count; i++){         //  radix sort
            u = a[i];
            m = u&0xff;
            b[mIndex[0][m]++] = u;
        }
        for(i = 0; i < count; i++){
            u = b[i];
            m = (u>>8)&0xff;
            a[mIndex[1][m]++] = u;
        }
        for(i = 0; i < count; i++){
            u = a[i];
            m = (u>>16)&0xff;
            b[mIndex[2][m]++] = u;
        }
        for(i = 0; i < count; i++){
            u = b[i];
            m = (u>>24)+128;
            a[mIndex[3][m]++] = u;
        }
    }

    public static void main(String[] args) {
        int[] a = new int[16*1024*1024];
        Random r = new Random(0);
        for(int i = 0; i < a.length; i++)
            a[i] = r.nextInt();
        long bgn, end;
        bgn = System.currentTimeMillis();
        RadixSort(a);
        end = System.currentTimeMillis();
        for(int i = 1; i < a.length; i++){
            if(a[i-1] > a[i]){
                System.out.println("failed");
                break;
            }
        }
        System.out.println("milliseconds " + (end-bgn));
    }
}

    @SuppressWarnings("empty-statement")
    public static void qsort(int[] a, int lo, int hi)
    {
        if(lo >= hi)
            return;
        int  p = a[lo+(hi-lo)/2];
        int  i = lo-1;
        int  j = hi+1;
        int t;
        while(true){                // partition
            while(a[++i] < p);
            while(a[--j] > p);
            if(i >= j)
                break;
            t     = a[i];
            a[i] = a[j];
            a[j] = t;
        }
        qsort(a, lo, j);
        qsort(a, j+1, hi);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM