希尔排序:(插入排序的优化)
思路:将数组元素分为gap组,分别对这gap组进行插入排序,再返回数组,重新分组,重复操作。当gap值为1时,所有元素统一在一组中进行排序。
gap的常用取值为:size/2,size/4…1;
当gap>1时,都是在预排序,目的是让数组更接近有序
当gap等于1时,数组已经接近有序了,最后再整体排序。
双重循环:
外部循环是要把所有的组都处理完毕。
内部循环是:先处理第一组的第一二个元素,再处理第二组的第一二个元素,再处理第三组的第一二个元素…内部循环只是处理当前组的一个比较和插入处理。
时间复杂度:理论极限值:O(N*1.3)(gap的值通过数学推导来取值。)一般情况下,按照size/2,size/4…的话,是O(N^2);
空间复杂度:O(1);
稳定性:不稳定(因为分组时,有可能会把相同的值分到不同组去进行比较)
package sort;
import java.util.Arrays;
public class shellSort {
public static void shellSort(int [] array){
int gap=array.length/2;
//gap的常用取值为:size/2,size/4.....1;
//当gap>1时,都是在预排序,目的是让数组更接近有序
// 当gap等于1时,数组已经接近有序了,最后再整体排序。
while (gap>1){
insertSortGap(array,gap);
gap=gap/2;
}
//循环结束后gap=1,进行最终的排序就ojkl
insertSortGap(array,1);
}
//分组插排,思路和插排一样,间隔为gap
private static void insertSortGap(int[] array, int gap) {
for (int bound=gap;bound<array.length;bound++){
int cur=bound-gap;//找同组中的上一个元素
int v=array[bound];
for (;cur>=0;cur-=gap){
if (array[cur]>v){
array[cur+gap]=array[cur];
}
else {
break;
}
}
array[cur+gap]=v;
}
}
public static void main(String[] args){
int [] array={9,6,0,3,1,7,8,4,5};
shellSort(array);
System.out.println(Arrays.toString(array));
}
}