为什么我的分拣程序这么慢? (java中的基数/桶排序)

时间:2016-03-12 16:57:38

标签: java sorting radix-sort bucket-sort

这是一个基数/桶排序混合,硬编码为9位数字。我的快速排序程序的速度是对10m数字进行排序的两倍多。我已经验证输出是正确的,它只是很慢。

代码:

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    ArrayList<Integer> inputs = new ArrayList<>();
    while (in.hasNext()) {
        inputs.add(in.nextInt());
    }
    radixSort(inputs);
    //System.out.print(toString(radixSort(inputs)));
}

public static ArrayList<Integer> radixSort(ArrayList<Integer> a) {
    for (int i = 1; i <= 9; i++) {
        a = bucketSort(a, i);
    }
    return a;
}

public static ArrayList<Integer> bucketSort(ArrayList<Integer> a, int index) {
    // Creates buckets
    ArrayList<ArrayList<Integer>> b = new ArrayList<ArrayList<Integer>>();
    for (int i = 0; i < 10; i++) {
        b.add(new ArrayList<Integer>());
    }
    // Sorts into buckets
    for (int i = 0; i < a.size(); i++) {
        b.get(key(a.get(i), index)).add(a.get(i));
    }
    // Concatenates buckets
    ArrayList<Integer> c = new ArrayList<>();
    for (int i = 0; i < b.size(); i++) {
        c.addAll(b.get(i));
    }
    return c;
}

// Takes an integer and index and returns digit at index
public static int key(int num, int ind) {
    int digit = num / (int)Math.pow(10, ind - 1);
    digit = digit % 10;
    return (int)digit;
}

public static String toString(ArrayList<Integer> a){ 
    StringBuilder s = new StringBuilder();
    for (int i = 0; i < a.size(); i++){
        s.append(String.format("%09d\n", a.get(i)));
    }
    return s.toString();
}

1 个答案:

答案 0 :(得分:0)

缓慢的主要原因是每次向每个桶阵列附加一个整数,必须再次附加才能连接桶,这涉及动态扩展阵列。

最低有效数字第一个桶排序的计数变化对第二个数组进行一次分配,其大小与原始数组相同。对于9位数示例,它可以为每个数字生成“0”,“1”,...“9”的出现次数计数,然后将计数转换为每个变量大小开头的起始索引桶,消除了连接的需要。对于9位数示例,矩阵[9] [10]可以用于计数/索引,因此只使用一次通过来生成矩阵。

维基文章:

{{3}}

示例C ++代码,使用字节大小的“数字”对32位无符号整数数组进行排序,因此计数/索引矩阵为[4] [256]。唯一的C ++部分是std :: swap(),否则就是C代码。

typedef unsigned int uint32_t;

//  a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0};            // count / index matrix
size_t i,j,m,n;
uint32_t u;
    for(i = 0; i < count; i++){         // generate histograms
        u = a[i];
        for(j = 0; j < 4; j++){
            mIndex[j][(size_t)(u & 0xff)]++;
            u >>= 8;
        }       
    }
    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(j = 0; j < 4; j++){             // radix sort
        for(i = 0; i < count; i++){     //  sort by current lsb
            u = a[i];
            m = (size_t)(u>>(j<<3))&0xff;
            b[mIndex[j][m]++] = u;
        }
        std::swap(a, b);                //  swap ptrs
    }
    return(a);
}