# 排序算法稳定性及桶排序

image.png

image.png

## 归并排序及快排的补充点

1. 归并排序的额外空间复杂度O(N)实际上可以转化为O(1)，搜索并参照归并排序内部缓存法。
2. 快速排序实际上可以做到稳定性，搜索并参照"01 stable sort"

## 比较器

``````import java.util.Arrays;
import java.util.Comparator;

public class Student {
public String name;
public int classes;

this.name = name;
this.classes = classes;
}

// 将班级按照升序排序
public static class ClassesAscendingComparator  implements Comparator<Student>{

@Override
public int compare(Student o1,Student o2){
return o1.classes - o2.classes;
}
}

// 将成绩按照升序排序
public static class GradesAscendingComparator  implements Comparator<Student>{

@Override
public int compare(Student o1,Student o2){
}
}

// print
public static void printStudents(Student[] students){
for(Student student:students){
}
System.out.println("=======================");
}

public static void main(String[] args){
Student s1 = new Student("王二毛",1,97);
Student s2 = new Student("李小虎",3,89);
Student s3 = new Student("李狗",2,88);
Student[] students = new Student[]{s1,s2,s3};
printStudents(students);
Arrays.sort(students,new ClassesAscendingComparator());
printStudents(students);
printStudents(students);
}
}
``````

``````班级：1姓名：王二毛成绩:97

=======================

=======================

=======================
``````

## 计数排序

``````// 本程序并未考虑待排序的数组中含负数，小数等情况
public class BucketSort {

public static int[] initBucket(int[] arr){
int maxNum = Integer.MIN_VALUE;
for(int i = 0;i < arr.length;i++){
maxNum = Math.max(arr[i],maxNum);
}
return new int[maxNum+1];
}
public static  void bucketSort(int[] arr){
if(arr == null || arr.length == 1)
return;

int[] bucket = initBucket(arr);
for(int i = 0;i < arr.length;i++){
bucket[arr[i]]++;
}
for(int i = 0,j = 0;i < bucket.length;i++){
if(bucket[i] != 0){
while(bucket[i]>0){
arr[j] = i;
j++;
bucket[i]--;
}
}
}
}
}
``````

``````// 具有稳定性的计数排序
public class BucketSort2 {

public static int[] initBucket(int[] arr){
int maxNum = Integer.MIN_VALUE;
for(int i = 0;i < arr.length;i++){
maxNum = Math.max(arr[i],maxNum);
}
return new int[maxNum+1];
}
public static  void bucketSort(int[] arr){
if(arr == null || arr.length == 1)
return;

int[] bucket = initBucket(arr);
for(int i = 0;i < arr.length;i++){
bucket[arr[i]]++;
}

// 稳定性改进
for(int i = 1;i < bucket.length;i++){
bucket[i] = bucket[i-1]+bucket[i];
}
int[] helpArr = new int[arr.length];

for(int i = arr.length-1;i >=0;i--){
helpArr[bucket[arr[i]] - 1] = arr[i];
bucket[arr[i]]--;
}
for(int i = 0;i < arr.length;i++){
arr[i] = helpArr[i];
}
}
}

``````

image.png

``````        for(int i = 1;i < bucket.length;i++){
bucket[i] = bucket[i-1]+bucket[i];
}
``````
image.png

bucket数组 bucket[index]不再表示index出现了多少个，而是表示包括index前面还有多少个数字。

## 基数排序

``````public class RadixSort {

public static int getMaxNumLength(int[] arr){
int max = Integer.MIN_VALUE;
for(int i = 0;i  < arr.length;i++){
max = Math.max(arr[i],max);
}
int len = 0;
while(max != 0){
max = max/10;
len++;
}
return len;
}

// 获取num第d位上的数字
public static int getBit(int num,int d){
return (int)((num % Math.pow(10,d))/Math.pow(10,(d-1)));
}

int maxNumLen = getMaxNumLength(arr);
int[] bucket = new int[10];
int[] helpArr = new int[arr.length];
for(int i = 1;i <= maxNumLen;i++){
for(int j = 0;j < bucket.length;j++){
bucket[j] = 0;
}
for(int j = 0;j < arr.length;j++){
bucket[getBit(arr[j],i)]++;
}
for(int j = 1;j<bucket.length;j++){
bucket[j] = bucket[j-1] + bucket[j];
}
for(int j = arr.length-1;j>=0;j--){
helpArr[bucket[getBit(arr[j],i)]-1] = arr[j];
bucket[getBit(arr[j],i)]--;
}
for(int j = 0;j < arr.length;j++){
arr[j] = helpArr[j];
}
}
}
}

``````

## 桶排序问题

``````给定一个数组，求如果排序之后，相邻两数的最大差值

``````

image.png

image.png

``````public class MaxGap2 {

// 最大数字无法使用whichBucket判断，当num为max时，结果应当为 whichBucket(max,len,max,min) - 1
public static int whichBucket(int num,int len,int max,int min){
return (int)((num - min) * len / (max - min));
}

public static int maxGap(int[] arr){
if(arr == null || arr.length <2)
return 0;

int minNum = Integer.MAX_VALUE;
int maxNum = Integer.MIN_VALUE;

int[] bucket = new int[arr.length+1];
for(int i = 0;i < arr.length;i++){
minNum = Math.min(minNum,arr[i]);
maxNum = Math.max(maxNum,arr[i]);
}

if(maxNum == minNum)
return 0;

boolean[] hasNum = new boolean[arr.length+1];
int[] maxBucketNum = new int[arr.length+1];
int[] minBucketNum = new int[arr.length+1];
for(int i = 0;i < arr.length;i++){
int bucketIndex = whichBucket(arr[i],arr.length+1,maxNum,minNum);
if(arr[i] == maxNum){
bucketIndex--;
}

if(!hasNum[bucketIndex]){
maxBucketNum[bucketIndex] = arr[i];
minBucketNum[bucketIndex] = arr[i];
hasNum[bucketIndex] = true;
}else{
maxBucketNum[bucketIndex] = arr[i] > maxBucketNum[bucketIndex] ? arr[i] : maxBucketNum[bucketIndex];
minBucketNum[bucketIndex] = arr[i] < minBucketNum[bucketIndex] ? arr[i] : minBucketNum[bucketIndex];
}
}

int maxBefore = maxBucketNum[0];
int maxGap = Integer.MIN_VALUE;
for(int i = 1;i < arr.length+1;i++){
if(hasNum[i]){
maxGap = Math.max((minBucketNum[i] - maxBefore),maxGap);
maxBefore = maxBucketNum[i];
}
}
return maxGap;
}
}
``````