计数排序
一.算法描述
* 找出待排序的数组中最大和最小的元素;
* 统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
* 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
* 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
二.代码实现
public int[] sort(int[] arr) {
int maxValue = getMaxValue(arr);
return countingSort(arr, maxValue);
}
private int[] countingSort(int[] arr, int maxValue) {
int bucketLen = maxValue + 1;
int[] bucket = new int[bucketLen];
for (int value : arr) {
bucket[value]++;
}
int sortedIndex = 0;
for (int j = 0; j < bucketLen; j++) {
while (bucket[j] > 0) {
arr[sortedIndex++] = j;
bucket[j]--;
}
}
return arr;
}
private int getMaxValue(int[] arr) {
int maxValue = arr[0];
for (int value : arr) {
if (maxValue < value) {
maxValue = value;
}
}
return maxValue;
}
三.复杂度分析
时间复杂度:O(n+k)
空间复杂度:O(n+k)
稳定性:稳定
桶排序
一.算法描述
* 假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序。
* 设置一个定量的数组当作空桶;
* 遍历输入数据,并且把数据一个一个放到对应的桶里去;
* 对每个不是空的桶进行排序;
* 从不是空的桶里把排好序的数据拼接起来。
二.代码实现
private static final int bucketSize = 5;
public static void main(String[] args) {
int[] nums = new int[]{2, 6, 8, 6, 6, 6, 9, 4, 5, 6};
BucketSort bucketSort = new BucketSort();
bucketSort.bucketSort(nums, bucketSize);
for (int num : nums) {
System.out.println(num);
}
}
private int[] bucketSort(int[] arr, int bucketSize) {
if (arr.length == 0) {
return arr;
}
int minValue = arr[0];
int maxValue = arr[0];
for (int value : arr) {
if (value < minValue) {
minValue = value;
} else if (value > maxValue) {
maxValue = value;
}
}
int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1;
int[][] buckets = new int[bucketCount][0];
// 利用映射函数将数据分配到各个桶中
for (int i = 0; i < arr.length; i++) {
int index = (int) Math.floor((arr[i] - minValue) / bucketSize);
buckets[index] = arrAppend(buckets[index], arr[i]);
}
int arrIndex = 0;
for (int[] bucket : buckets) {
if (bucket.length <= 0) {
continue;
}
// 对每个桶进行排序,这里使用了插入排序,length<47 插入排序, length<286 快速排序
Arrays.sort(bucket);
for (int value : bucket) {
arr[arrIndex++] = value;
}
}
return arr;
}
private int[] arrAppend(int[] arr, int value) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}
三.复杂度分析
时间复杂度:平均 O(n+k) 最坏O(n²) 最好O(n)
空间复杂度:O(n+k)
稳定性:稳定
基数排序
一.算法描述
* 假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序。
* 设置一个定量的数组当作空桶;
* 遍历输入数据,并且把数据一个一个放到对应的桶里去;
* 对每个不是空的桶进行排序;
* 从不是空的桶里把排好序的数据拼接起来。
二.代码实现
public int[] sort(int[] arr) {
int maxDigit = getMaxDigit(arr);
return radixSort(arr, maxDigit);
}
private int getMaxDigit(int[] arr) {
int maxValue = getMaxValue(arr);
return getNumLenght(maxValue);
}
private int getMaxValue(int[] arr) {
int maxValue = arr[0];
for (int value : arr) {
if (maxValue < value) {
maxValue = value;
}
}
return maxValue;
}
protected int getNumLenght(long num) {
if (num == 0) {
return 1;
}
int lenght = 0;
for (long temp = num; temp != 0; temp /= 10) {
lenght++;
}
return lenght;
}
private int[] radixSort(int[] arr, int maxDigit) {
int mod = 10;
int dev = 1;
for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
// 考虑负数的情况
int[][] counter = new int[mod * 2][0];
for (int j = 0; j < arr.length; j++) {
int bucket = ((arr[j] % mod) / dev) + mod;
counter[bucket] = arrayAppend(counter[bucket], arr[j]);
}
int pos = 0;
for (int[] bucket : counter) {
for (int value : bucket) {
arr[pos++] = value;
}
}
}
return arr;
}
private int[] arrayAppend(int[] arr, int value) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}
三.复杂度分析
时间复杂度:O(n*k)
空间复杂度:O(n+k)
稳定性:稳定