基数排序实现

时间:2015-10-25 06:31:09

标签: java sorting computer-science radix-sort

我正在尝试制作基数排序函数,该函数使用基数排序作为基数来计算整数的位数,然后将数字从最不重要到最重要的排序。

我正在使用一个包含随机整数的数组。

如何让这种方法运作良好?

我正在使用此代码:

public static void sort( int[] a, int radix)
    {
        int i, m = a[0], exp = 1, n = a.length;
        int[] b = new int[10];
        for (i = 1; i < n; i++)
            if (a[i] > m)
                m = a[i];
        while (m / exp > 0)
        {
            int[] bucket = new int[10];

            for (i = 0; i < n; i++)
                bucket[(a[i] / exp) % 10]++;
            for (i = 1; i < 10; i++)
                bucket[i] += bucket[i - 1];
            for (i = n - 1; i >= 0; i--)
                b[--bucket[(a[i] / exp) % 10]] = a[i];
            for (i = 0; i < n; i++)
                a[i] = b[i];
            exp *= 10;        
        }
    }    

3 个答案:

答案 0 :(得分:0)

我只是指出最明显的问题,并将细节留给您。

每个存储桶都必须包含一个数字列表,因此仅使用int作为存储桶是行不通的。请改用这样的东西:

List<Integer>[] bucket = new List<Integer>[10];

用于收集新订单中元素的数组需要与原始数组的大小相同。你刚刚做了10长。

答案 1 :(得分:0)

尝试

    int[] b = new int[a.length];

或者因为n = a.length

    int[] b = new int[n];

答案 2 :(得分:0)

对于非负整数,使用binary代替decimal可能对机器更有效且更直观。

这是我编写的带有测试用例的实现:

RadixSort.java

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * Radix sort.
 *
 * @author eric
 * @date 3/12/20 12:05 PM
 */
public class RadixSort {
    /**
     * Sort given array, the array will be modified.
     *
     * @param data array of integer of non-negative integers,
     * @throws IllegalArgumentException if input contain negative integer,
     */
    public static void sort(int[] data) {
        int numSys = 2;
        int bits = validAndfindHighestBit(data); // find highest bit,

        // create queues,
        List<List<Integer>> queues = new ArrayList<>(numSys);
        for (int i = 0; i < numSys; i++) queues.add(new LinkedList<>());

        // sort bit by bit, low to high,
        for (int i = 0; i < bits; i++) {
            // re-init queues,
            for (int j = 0; j < numSys; j++) queues.get(j).clear();

            // array -> queues,
            for (int x : data) {
                int bit = (x >> i) & 1; // get the i-th bit,
                queues.get(bit).add(x);
            }

            // queues -> array,
            int t = 0;
            for (List<Integer> queue : queues) {
                for (int x : queue) data[t++] = x;
            }
        }
    }

    /**
     * Valid input number, and find highest bit that has 1.
     *
     * @param data
     * @return
     * @throws IllegalArgumentException if input contain negative integer,
     */
    private static int validAndfindHighestBit(int[] data) {
        // find max number,
        int max = 0;
        for (int x : data) {
            if (x < 0) throw new IllegalArgumentException("negative integers are not supported");
            if (x > max) max = x;
        }
        System.out.printf("max number: %d, ", max);

        // find highest bit,
        int highestBit = 0;
        while (max != 0) {
            highestBit++;
            max >>= 1;
        }
        System.out.printf("highest bit: %d\n", highestBit);

        return highestBit;
    }
}

RadixSortTest.java
(通过TestNG的测试用例)

import org.testng.Assert;
import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

import static org.testng.Assert.*;

/**
 * RadixSort test.
 */
public class RadixSortTest {
    @Test
    public void testSort() {
        int[] data;
        // generated un-sorted random array,
        do data = genRandomArr(); while (data.length > 1 && isSorted(data));
        System.out.printf("input arr:\t%s\n", Arrays.toString(data));
        if (data.length > 1) Assert.assertFalse(isSorted(data));

        // sort
        RadixSort.sort(data);
        System.out.printf("output arr:\t%s\n", Arrays.toString(data));
        Assert.assertTrue(isSorted(data));
    }

    // corner case,
    @Test
    public void testSort_corner() {
        int[] dataEmpty = new int[0]; // empty array,
        RadixSort.sort(dataEmpty);
        Assert.assertTrue(isSorted(dataEmpty));

        int[] dataSingle = new int[]{5}; // single element,
        RadixSort.sort(dataSingle);
        Assert.assertTrue(isSorted(dataSingle));
    }

    // invalid input,
    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testSort_invalid() {
        int[] dataSingle = new int[]{1, -1}; // negative number,
        RadixSort.sort(dataSingle);
    }

    /**
     * generate random array, of size 10, in range [0, 1024),
     *
     * @return
     */
    public static int[] genRandomArr() {
        return genRandomArr(10, 100);
    }

    /**
     * generate random array,
     *
     * @param size  array size, default to 10,
     * @param bound upper bound, default to 100,
     * @return
     */
    public static int[] genRandomArr(int size, int bound) {
        if (size <= 0) size = 10;
        if (bound <= 0) bound = 100;
        ThreadLocalRandom rd = ThreadLocalRandom.current();
        int[] arr = new int[size];
        for (int i = 0; i < arr.length; i++) arr[i] = rd.nextInt(bound);
        return arr;
    }

    // check whether array is sorted,
    private static boolean isSorted(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            if (a[i] > a[i + 1]) return false;
        }
        return true;
    }
}