记录一下,以后面试的时候过来背背
希尔排序
希尔排序又称“增量排序”,是直接插入排序算法的改进版本,对于中等规模数据的性能表示不错
排序思想
希尔分组会将目前较大的分组分成若干份小组,然后分别对每一个小组进行直接插入排序,此时,由于分组较小,使用插入排序效率高
希尔排序分组的标准是按照数组的length/2的下标相隔距离来进行分组的,这里下标之间的差值或距离被称为增量。再对每一组进行排序后,每个小组都有序了,虽然整个数组仍然不是有序的,所以我们可以接着进行循环,也就是使增量/2
可以看到这里增量为2,同理对每个分组进行排序,使得各个分组各自有序,最后得到的数组由于增量/2为1,则整个数组被分为了一组,此时的数组接收插入排序效率较高
代码实现
public static void shellSort(int[] array){
for(int gap = array.length / 2; gap > 0; gap /= 2){
for(int i = gap; i < array.length; i++){
int j = i; //记录下标
int temp = array[j]; //记录要位移的值
if(array[j] < array[j-gap]){
//如果j下标处的数字小于j-gap下标处的数字
while(j - gap >= 0 && temp < array[j-gap]){
//移动
array[j]=array[j-gap];
j -= gap;
}
//退出循环后就找了temp的插入位置
array[j] = temp;
}
}
}
}
快速排序
快速排序由于排序效率在同为O(N*logN)
的几种排序方法中效率较高,又因为分治法确实实用,所以面试经常有,基本思想:
- 先从数列中取出一个数作为基准数
- 分区过程中,较大的数放到它的右边,较小或等于它的数放到它的左边
- 再对左右分区重复第二步,直到各区间只有一个数
排序思想
假设最开始我们选择的基准数是数组的第一位,此时我们还需要用一个mid取去存储基准数,设置两个记录下标left=0
,right=array.length-1
,读取位置是设置基准数的相反位置
代码实现
public static void quick_sort(int[] array, int left, int right){
if(left < right){
int mid = get_mid(array, left, right);
quick_sort(array, left, mid-1);
quick_sort(array, mid+1, right);
}
}
public static int get_mid(int[] array, int left, int right){
int pivot = array[left];
while(left < right){
while(array[right]>=pivot && left < right) right--;
array[left] = array[right];
while(array[left] <= pivot && left < right) left++;
array[right] = array[left];
}
array[left] = pivot;
return left;
}
基数排序
又称“桶子法”,从低位开始将待排序的数按照这一位的值放到相应的编号为0~9的桶中。等到低位排完得到一个子序列,再将这个序列按照次低位的大小进入相应的桶中,一直排到最高位为止,数组排序完成
代码实现
public static void radixSort(int[] arr){
//定义一个二维数组表示10个桶 每个桶就是一个一维数组
int[][] bucket = new int[10][arr.length];
//为了记录每个桶中 实际存放了多个个数据,定义一个一维数组记录每个桶中每次放入的数据个数
int[] bucketElementCount = new int[10];
//先遍历得到数组中最大的数和它的位数
int max = arr[0];
for(int i = 0; i < arr.length; i++){
if(arr[i] > max) max = arr[i];
}
//得到最大位数
int maxLength = (max + "").length();
//n用来控制位数
for(int i = 0, n = 1; i < maxLength; i++, n*=10){
for(int j = 0; j < arr.length; j++){
//取出每个元素的个位的值
int digitOfElement = arr[j] / n % 10;
//放到对应的桶中
bucket[digitOfElement][bucketElementCount[digitOfElement]] = arr[j];
bucketElemerntCount[digitOfElement]++;
}
int index = 0;
//按照这个桶的顺序取出数据 放入到原来的数组中
for(int k = 0; k <bucketElementCount.length; k++){
//如果桶中有数据 才能放置
if(bucketElementCount[k] != 0){
for(int l = 0; ; < bucketElementCount[k]; l++){
arr[index++]=bucket[k][l];
}
}
bucketElementCount[k] = 0;
}
}
}