You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
3.0 KiB
Java
94 lines
3.0 KiB
Java
5 years ago
|
package com.jwetherell.algorithms.sorts;
|
||
|
|
||
|
/**
|
||
|
* An American flag sort is an efficient, in-place variant of radix sort that
|
||
|
* distributes items into hundreds of buckets. Non-comparative sorting
|
||
|
* algorithms such as radix sort and American flag sort are typically used to
|
||
|
* sort large objects such as strings, for which comparison is not a unit-time
|
||
|
* operation.
|
||
|
*
|
||
|
* Family: Bucket.
|
||
|
* Space: In-place.
|
||
|
* Stable: False.
|
||
|
*
|
||
|
* Average case = O(n*k/d) Worst case = O(n*k/d) Best case = O(n*k/d)
|
||
|
* NOTE: n is the number of digits and k is the average bucket size
|
||
|
*
|
||
|
* http://en.wikipedia.org/wiki/American_flag_sort
|
||
|
*
|
||
|
* @author Justin Wetherell <phishman3579@gmail.com>
|
||
|
*/
|
||
|
public class AmericanFlagSort {
|
||
|
|
||
|
private static final int NUMBER_OF_BUCKETS = 10; // 10 for base 10 numbers
|
||
|
|
||
|
private AmericanFlagSort() { }
|
||
|
|
||
|
public static Integer[] sort(Integer[] unsorted) {
|
||
|
int numberOfDigits = getMaxNumberOfDigits(unsorted); // Max number of digits
|
||
|
int max = 1;
|
||
|
for (int i = 0; i < numberOfDigits - 1; i++)
|
||
|
max *= 10;
|
||
|
sort(unsorted, 0, unsorted.length, max);
|
||
|
return unsorted;
|
||
|
}
|
||
|
|
||
|
public static void sort(Integer[] unsorted, int start, int length, int divisor) {
|
||
|
// First pass - find counts
|
||
|
int[] count = new int[NUMBER_OF_BUCKETS];
|
||
|
int[] offset = new int[NUMBER_OF_BUCKETS];
|
||
|
int digit = 0;
|
||
|
for (int i = start; i < length; i++) {
|
||
|
int d = unsorted[i];
|
||
|
digit = getDigit(d, divisor);
|
||
|
count[digit]++;
|
||
|
}
|
||
|
offset[0] = start + 0;
|
||
|
for (int i = 1; i < NUMBER_OF_BUCKETS; i++) {
|
||
|
offset[i] = count[i - 1] + offset[i - 1];
|
||
|
}
|
||
|
// Second pass - move into position
|
||
|
for (int b = 0; b < NUMBER_OF_BUCKETS; b++) {
|
||
|
while (count[b] > 0) {
|
||
|
int origin = offset[b];
|
||
|
int from = origin;
|
||
|
int num = unsorted[from];
|
||
|
unsorted[from] = -1;
|
||
|
do {
|
||
|
digit = getDigit(num, divisor);
|
||
|
int to = offset[digit]++;
|
||
|
count[digit]--;
|
||
|
int temp = unsorted[to];
|
||
|
unsorted[to] = num;
|
||
|
num = temp;
|
||
|
from = to;
|
||
|
} while (from != origin);
|
||
|
}
|
||
|
}
|
||
|
if (divisor > 1) {
|
||
|
// Sort the buckets
|
||
|
for (int i = 0; i < NUMBER_OF_BUCKETS; i++) {
|
||
|
int begin = (i > 0) ? offset[i - 1] : start;
|
||
|
int end = offset[i];
|
||
|
if (end - begin > 1)
|
||
|
sort(unsorted, begin, end, divisor / 10);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static int getMaxNumberOfDigits(Integer[] unsorted) {
|
||
|
int max = Integer.MIN_VALUE;
|
||
|
int temp = 0;
|
||
|
for (int i : unsorted) {
|
||
|
temp = (int) Math.log10(i) + 1;
|
||
|
if (temp > max)
|
||
|
max = temp;
|
||
|
}
|
||
|
return max;
|
||
|
}
|
||
|
|
||
|
private static int getDigit(int integer, int divisor) {
|
||
|
return (integer / divisor) % 10;
|
||
|
}
|
||
|
}
|