🟡前言
21天挑战赛的第五天,本文主要讲述希尔排序,也是插入排序的改良版
活动地址:CSDN21天学习挑战赛
🟡概述
1️⃣排序原理
1.选定一个增长量h,按照增长量h作为数据分组依据,对数组进行分组
2.对每个分好组的进行排序·
3.减少增长量,最小为1,重复第二步
此处组内排序是运用插入排序的方法,而不是单纯的两两交换
2️⃣原理图
第一次将数据分为五组:下标为{0,5},{1、6},{2、7},{3、8},{4、9},然后每组内元素对比,小的在前
第二次将数据分为两组:下标为0、2、4、6、8的一组,下标为1、3、5、7、9的一组然后每组内元素运用插入排序的方法进行排序
第三次就是相邻两两比较,然后排序,即整个数组运用插入排序的方法进行排序
由于此时数组并不是完全混乱的,所以移动的数据量会更少,提高效率
🟡调用API解决
1️⃣构造方法和成员方法
构造方法
Shell()
成员方法
public static void sort(Comparable[]a)
:对数组a中元素进行排序
public static boolean greater(Comparable x, Cpmparable y)
:判断x是否大于y;
一般使用时会这么写:x.compareTo(y) ,再判断值是否 >0 , >0则表示 x>y
public static void exch(Comparable[]a, int i, int j)
:交换数组a中下标为 i 和 j 的元素
2️⃣增长量
一般会取长度的一般,即 h = h / 2
严谨一点应该如下
int N = a.length; int h = 1; while (h < N/2){ h = 2 * h + 1; }
3️⃣解题思路
1.想要对数组内元素进行排序,就要调用 public static void sort(Comparable[]a)
2.依次比较待插入元素 i 和分组内另一个元素,就需要用到for循环语句;当h = 5 时,a[5]恰好是数组内第6个元素,也就是第一个待插入的元素,所以初始条件是 i = h,待插入的最后一个元素就是数组内最后一个元素,即终止条件为 i < a.length
3.每组比较的元素有个共同特点是:组内后者元素下标 i — 组内前者元素下标 j = h,即 j = i - h,所以这里也要添加一个内循环来找出与待排序元素一组的元素
4.利用插入排序的方法比较组内元素 a[ j - h ] 和 a[ j ] 大小
5.转换成字符串类型后打印输出
4️⃣代码实现
public class ShellSort { public static void sort(Comparable[] a){ int N = a.length; int h = 1; while (h < N/2){ h = 2 * h + 1; } while (h >= 1){ for(int i = h; i < a.length ; i++){ for (int j = i; j >=h; j -= h){ if(greater(a[j-h],a[j])){ exch(a,j-h,j); } else { break; } } } } } private static boolean greater(Comparable x, Comparable y){ return x.compareTo(y) > 0; } private static void exch(Comparable[] a, int i, int j){ Comparable temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } }
public class ShellSortTest { public static void main(String[] args) { Integer[] arr = {9,1,2,5,7,4,8,6,3,5}; ShellSort.sort(arr); System.out.println(Arrays.toString(arr)); } }
🟡空间复杂度
希尔排序的时间复杂度取决于h的取值,不同取值的复杂度不同,所以不展开讲述,其时间复杂度的范围是O(N^(3/2))~n * log2n之间
🟡结语
希尔排序是高级排序的一种,虽然书写代码时是交换数据,但是不能将组内元素排序理解为两两交换,而是组内运用插入排序的算法进行排序