要点:利用了插入排序对于数据有序性的依赖,先对部分元素位置进行调整,再执行插入排序。整体上降低了插入排序的时间复杂度,是插入排序的改进版本。当然,人品好的,还是用插入吧。
1 import java.util.Random; 2 3 public class ShellSort<T extends Comparable> { 4 5 public void sort(T[] arr) { 6 // 数据间距 7 int space = arr.length / 2; 8 while (space >= 1) { 9 // 当前元素下标 10 int index = 0; 11 // 每组首元素的下标 12 int move = 0; 13 // 按照间距能分出的数据组数 14 double capcity = Math.floor(arr.length / Math.floor(arr.length / space)); 15 printArr(arr); 16 while (move < capcity) { 17 // 下一个元素下标 18 int next = index + space; 19 // 对比交换 20 if (arr[index].compareTo(arr[next]) > 0) { 21 printIndex(index, next); 22 T temp = arr[next]; 23 arr[next] = arr[index]; 24 arr[index] = temp; 25 } 26 // 当前坐标移动 27 index = next; 28 // 一组元素执行完进入下一组,首元素后移一位,当前坐标移至首元素位置 29 if (index + space >= arr.length) { 30 index = ++move; 31 } 32 } 33 // 当拆分的组数只有1组时,执行插入排序 34 if (capcity == 1) { 35 for (int i = 1; i < arr.length; i++) { 36 if (arr[i].compareTo(arr[i - 1]) < 0) { 37 printArr(arr); 38 T temp = arr[i]; 39 for (int j = i; j > 0; j--) { 40 arr[j] = arr[j - 1]; 41 if (arr[j - 1].compareTo(temp) <= 0) { 42 arr[j] = temp; 43 break; 44 } 45 } 46 printArr(arr); 47 } 48 } 49 } 50 // 间距减半 51 space /= 2; 52 } 53 } 54 55 private void printIndex(int index, int next) { 56 String[] stringArr = new String[]{"|", "|", "|", "|", "|", "|", "|", "|", "|", "|", "|"}; 57 stringArr[index] = "*"; 58 stringArr[next] = "*"; 59 for (String s : stringArr) { 60 System.out.print(s); 61 } 62 System.out.println(); 63 } 64 65 private void printArr(T[] arr) { 66 for (T n : arr) { 67 System.out.print(n); 68 } 69 System.out.println(); 70 } 71 72 public static void main(String[] args) { 73 int n = 11; 74 Integer[] arr = new Integer[n]; 75 for (int i = 0; i < n; i++) { 76 arr[i] = new Random().nextInt(10); 77 } 78 ShellSort ss = new ShellSort(); 79 ss.sort(arr); 80 } 81 82 /** 83 * 60372574404 => 原始数据, 按照间隔``arr.length/2``拆分 84 * *||||*||||| => 交换 85 * |||||*||||* => 交换 => 发生了顺序改变,因此不稳定 86 * |||*||||*|| => 交换 87 * ||||*||||*| => 交换 88 * 50340474726 => 间隔减半,由5变2 89 * *|*|||||||| => 交换 90 * ||*|*|||||| => 交换 91 * ||||||||*|* => 交换 92 * |||||||*|*| => 交换 93 * 30045472647 => 间隔减半,由2变1 94 * **||||||||| => 交换 95 * |**|||||||| => 交换 96 * ||||**||||| => 交换 97 * ||||||**||| => 交换 98 * |||||||**|| => 交换 99 * ||||||||**| => 交换 100 * 00344526477 => 开始执行插入排序,发现2 101 * ^ 102 * 00234456477 => 将2插入到有序位置 103 * 00234456477 => 发现4 104 * ^ 105 * 00234445677 => 将4插入到有序位置 106 * 107 * 序列按排序方向的有序性越高,插入排序越快 108 * 希尔排序是尽可能先排好序,再执行插入,是插入排序的改进版 109 * 插入拼人品,希尔求稳定 110 * => 遍历次数:与数据分布有关 111 * => 时间复杂度:最小为O(nlogn) 112 * => 稳定性:不稳定 113 */ 114 115 }