import java.util.Arrays;import org.junit.Test;/** * 希尔排序 * 插入排序的一种 */public class HeerSort { //希尔排序,它包括了交换法和移动法两种方式 public int[] heerSort(int[] arrays){ if(null == arrays){ throw new NullPointerException("arrays is null"); } if(!(arrays.length>0)){ return arrays; } int[] sortArrays = Arrays.copyOf(arrays, arrays.length);// sort(sortArrays); sortOpt(sortArrays); return sortArrays; } //移动法 private int[] sort(int[] sortArrays){ int length = sortArrays.length; // 先求出最大区间值 int rCtl = 1; while(rCtl*2+2<length){ rCtl = rCtl*2+2; } // 循环---将区间值减半 while (rCtl>0){ // 从第rCtl位开始,按区间进行插入排序 for(int i = rCtl;i<rCtl*2;i++){ // [1,*,*,*,3,*,*,*,2,*,*,*,7,*,*,*,5,*,*,*] for(int j = i;j<length;j+=rCtl){ // 找到插入的位置 int insertnum = j; int temp = sortArrays[j]; for(int c = j-rCtl;c>=0;c-=rCtl){ // 将在j前面的值,如果大于j,就往后挪一位 if(sortArrays[c]>temp){ sortArrays[c+rCtl] = sortArrays[c]; insertnum = c; }else{ break; } } sortArrays[insertnum] = temp; } } rCtl=rCtl/2; } return sortArrays; } //代码优化写法 // 最外部不需要跨区间去循环,将外部跨区间循环与区间内部循环合成一个循环 // 因为本质还是从 0+fctl的位置一直遍历到最后一个 private void sortOpt(int[] arrays){ int len = arrays.length; //定义区间大小 int fctl = 1; //计算出最大区间 while(2*fctl+2<len){ fctl = 2*fctl+2; } while(fctl>0){ for(int i = fctl;i<len;i++){ int sortValue = arrays[i]; int insertKey = i; //找到待排序的值所在的分组中该插入的位置 while((insertKey-fctl)>=0&&sortValue<arrays[insertKey-fctl]){ arrays[insertKey] = arrays[insertKey-fctl]; insertKey-=fctl; } arrays[insertKey] = sortValue; } fctl = fctl/2; } } @Test public void test(){ int [] arr1 = new int[]{9,3,5,7,2,8,4,1,6,2}; System.out.println(Arrays.toString(heerSort(arr1))); }}