算法 - 希尔排序

要点:利用了插入排序对于数据有序性的依赖,先对部分元素位置进行调整,再执行插入排序。整体上降低了插入排序的时间复杂度,是插入排序的改进版本。当然,人品好的,还是用插入吧。

  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 }

 

posted @ 2020-04-29 10:38  御简  阅读(131)  评论(0编辑  收藏  举报