import java.util.Arrays;
/**
* 希尔排序。属于直接(简单)插入排序的变种。可以减少元素移动的次数。
* 另外,由于记录是跳跃式的移动,所以希尔排序不是一种稳定的排序算法。
*/
public class ShellSort {
public static void sortAsc(int[] arr) {
if (arr == null || arr.length <= 1)
return;
int i, j;
int incr = arr.length;
int count = 0; // 记录元素移动的次数
do {
incr = incr / 3 + 1; // 不一定非要除以3,但增量序列的最后一个增量值必须等于1
for (i = incr; i < arr.length; i++) {
if (arr[i] < arr[i - incr]) {
int t = arr[i];
for (j = i - incr; j >= 0 && t < arr[j]; j -= incr) {
arr[j + incr] = arr[j];
count++;
}
arr[j + incr] = t;
count++;
}
}
} while (incr > 1);
System.out.println("移动元素的次数:" + count);
}
public static void sortDesc(int[] arr) {
if (arr == null || arr.length <= 1)
return;
int i, j;
int incr = arr.length;
do {
incr = incr / 3 + 1;
for (i = incr; i < arr.length; i++) {
if (arr[i] > arr[i - incr]) {
int t = arr[i];
for (j = i - incr; j >= 0 && t > arr[j]; j -= incr)
arr[j + incr] = arr[j];
arr[j + incr] = t;
}
}
} while (incr > 1);
}
public static void main(String[] args) {
testCase4();
}
public static void testCase() {
int[] arr = {3, 2};
sortAsc(arr);
System.out.println(Arrays.toString(arr));
sortDesc(arr);
System.out.println(Arrays.toString(arr));
}
public static void testCase1() {
int[] arr = {3, 1, 2};
sortAsc(arr);
System.out.println(Arrays.toString(arr));
sortDesc(arr);
System.out.println(Arrays.toString(arr));
}
public static void testCase2() {
int[] arr = {20, 11, 21, 3, 1, 25, 2, 0};
sortAsc(arr);
System.out.println(Arrays.toString(arr));
sortDesc(arr);
System.out.println(Arrays.toString(arr));
}
public static void testCase3() {
int[] arr = {25, 21, 20, 18, 17, 13, 11, 9, 7, 3, 2, 1, 0};
sortAsc(arr);
System.out.println(Arrays.toString(arr));
}
public static void testCase4() {
int[] arr = {6, 3, 3, 3, 1, 4, 2};
sortAsc(arr);
System.out.println(Arrays.toString(arr));
sortDesc(arr);
System.out.println(Arrays.toString(arr));
}
}
对于将数组{25, 21, 20, 18, 17, 13, 11, 9, 7, 3, 2, 1, 0}按照正序排序这种极端情况,希尔排序需要移动元素29次,而直接插入排序需要移动元素90次。