目录
一.希尔排序介绍:
希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。它通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟为止。
希尔排序的基本思想是将整个待排序的记录序列分割成若干个子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。这里“基本有序”是相对概念,它是希尔排序能够提高排序效率的关键。
二.希尔排序的基本步骤:
-
初始化间隔序列:希尔排序的第一步是选择一个间隔序列t1,t2,……,tk,其中ti > tj,对于所有i<j。最简单的间隔序列是希尔原始序列:n/2,n/4,…,1。
-
分组插入排序:按照间隔序列的第一个间隔数t1,将排序序列分成若干长度为t1的子序列,分别对这些子序列进行直接插入排序。
-
缩小间隔并重复:然后取第二个间隔数t2,重复上述分组排序过程,直到间隔数为1,也就是所有元素都在同一组内进行直接插入排序。
-
最终排序:当间隔数为1时,整个文件恰被分成一组,算法便终止。
三.希尔排序的java代码实现:
public class ShellSort {
public static void main(String[] args) {
int[] arr={8,9,1,7,2,3,5,4};
int n=arr.length;
// 初始增量为数组长度的一半
for (int gap = n / 2; gap > 0; gap /= 2) {
// 从第gap个元素开始,逐个对其所在的子序列进行直接插入排序
for (int i = gap; i < n; i++) {
int j = i;
int temp = arr[j];
// 插入排序的步骤
while (j - gap >= 0 && temp < arr[j - gap]) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
for (int i : arr) {
System.out.print(i+" ");
}
}
}
四.运行过程:
五.希尔排序和插入排序:
希尔排序内部用了插入排序,如果对插入排序有疑问的可以看
希尔排序(Shell Sort)相比插入排序(Insertion Sort)有更好的性能,特别是在处理大数据集时。这是因为希尔排序在插入排序的基础上增加了一个新的特性:它允许交换不相邻的元素以改善序列的局部排序。以下是希尔排序相比插入排序的一些优势:
-
减少比较和交换的次数:在插入排序中,每插入一个元素可能需要移动大量元素。希尔排序通过允许远距离的交换,可以在较早的阶段就达到部分排序,从而减少了后续排序过程中需要移动元素的次数。
-
更有效的移动:希尔排序通过使用一个递减的序列(称为增量序列)来定义元素之间的间隔,这意味着在排序的早期阶段,元素可以移动到相对较远的位置,从而更快地移到正确位置附近。随着排序的进行,增量逐渐减小,最终变为1,这时算法类似于传统的插入排序,但因为前期的大幅度移动,此时的数组已经接近有序,所以需要的交换和比较次数大大减少。
-
适应不同规模的数据集:希尔排序通过选择合适的增量序列,可以更好地适应不同的数据集。例如,对于中等大小的数据集,希尔排序可以提供比插入排序更好的性能。
-
减少逆序对的数量:在数据集中,逆序对(即不符合升序排列的元素对)会影响插入排序的性能。希尔排序通过在排序初期就减少逆序对的数量,使得整个排序过程更加高效。
总结:
希尔排序的时间复杂度与所选取的步长序列有很大关系,已知的最好的步长序列使得希尔排序的时间复杂度可以达到 O(nlog2n)。在最坏的情况下,希尔排序的时间复杂度仍然是 O(n2),但它比简单插入排序要快得多,因为随着排序的进行,序列变得越来越有序,使得插入排序的效率越来越高。
希尔排序的空间复杂度为 O(1),因为它只需要一个额外的存储空间来进行交换。
总体来说,希尔排序是一个相对高效的排序算法,特别是对于中等大小的数组。它比传统的插入排序更快,比快速排序和归并排序等高级排序算法更简单,因此在实际应用中仍然有一定的使用价值。