[英]Radix sort implementation
我正在嘗試制作基數排序函數,該函數使用基數排序作為基數來計算整數的位數,然后將數字從最不重要到最重要。
我正在使用一個包含隨機整數的數組。
我怎樣才能使這種方法運作良好?
我正在使用此代碼:
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;
}
}
我只是指出最明顯的問題,把細節留給你。
每個存儲桶都必須保存一個數字列表,因此僅使用int
作為存儲桶是行不通的。 使用類似這樣的東西:
List<Integer>[] bucket = new List<Integer>[10];
用於按新順序收集元素的數組需要與原始數組大小相同。 你剛剛做了 10 長。
嘗試
int[] b = new int[a.length];
或者因為 n = a.length
int[] b = new int[n];
最后一個 for 循環中的語句
a[i] = b[i];
告訴 b 的大小必須等於或大於 a。 因此去@rcgldr 回答。 傳遞給函數的基數值也未使用。 您還可以通過交換數組指針而不是復制元素來使您的函數更快一點,即避免最后一個 for 循環。
int swap[] = a;
a = b;
b = swap;
然后最后在所有循環結束后,返回數組 a
return a;
以上是您按升序排序的程序。 我在程序下面給出按降序排序。 唯一需要的改變是開始添加從基本數組(在本例中為 Z )末尾到索引零的頻率。
public static int[] DSC(int A[], int radix, int base)
{
int length = A.length ;
int B[] = new int[length] ;
int div = 1 ;
int swap[] ;
int i ;
while(radix > 0)
{
int Z[] = new int[base] ;
i = 0 ;
while(i < length)
{
Z[( A[i] / div ) % base]++ ;
i++ ;
}
i = base ;
while(i > 1)
{
i--;
Z[i-1] += Z[i] ;
}
i = length ;
while(i > 0)
{
i-- ;
B[--Z[( A[i] / div ) % base]] = A[i];
}
swap = A;
A = B;
B = swap;
div *= base;
radix--;
}
return A;
}
對於非負整數,使用binary
而不是decimal
,可能對機器更有效和直觀。
這是我寫的一個實現,帶有測試用例:
基數排序程序
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;
}
}
基數排序測試.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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.