希尔排序解读(基于java实现)

2023-12-24 09:43:33 浏览数 (1)

概述

希尔排序(Shell Sort)是一种基于插入排序的排序算法,通过将待排序的元素分组进行插入排序,逐步减小分组的间隔,最终使整个序列有序。

希尔排序的基本思想是将待排序的序列划分为若干个较小的子序列,对这些子序列进行插入排序。初始时,选择一个较大的间隔值(称为增量),按照该增量将序列分成多个子序列,并对每个子序列进行插入排序。然后逐渐缩小增量,重复进行分组和插入排序,直到增量为1,完成最后一次插入排序,整个序列就变成有序的。

具体的步骤如下:

  1. 选择一个增量值(通常为数组长度的一半),并设定为gap。
  2. 根据增量gap,将待排序序列分成若干个子序列,每个子序列相邻元素之间的间隔为gap。
  3. 对每个子序列进行插入排序,即从第gap个元素开始,按照插入排序的方式将元素插入到前面已排序的子序列中。
  4. 缩小增量gap,重复步骤3,直至gap为1,完成最后一次插入排序。

时间空间复杂度分析

时间复杂度: 希尔排序的时间复杂度是比较复杂的,由于增量序列的选择不同,最坏情况下的时间复杂度可以达到O(n^2),但在一般情况下,希尔排序的平均时间复杂度为O(n log n)。

究其原因,希尔排序通过将待排序序列划分为若干个子序列进行插入排序,每次排序时的间隔逐渐缩小。这样可以使得在初始阶段,每个子序列中的元素之间相隔较远,通过一次插入排序可以快速将较小的元素移动到正确的位置。随着间隔的缩小,每次排序时元素之间的距离逐渐变小,最终在增量为1时完成排序。

空间复杂度: 希尔排序是一种原地排序算法,它只需要常数级别的额外空间来存储临时变量,所以其空间复杂度为O(1)。

基于java实现

代码语言:javascript复制
package day1120;

public class ShellSort {
    public static void shellSort(int[] arr) {
        int n = arr.length;

        // 初始增量为数组长度的一半,然后逐渐缩小增量
        for (int gap = n / 2; gap > 0; gap /= 2) {
            // 对每个子序列进行插入排序
            for (int i = gap; i < n; i  ) {
                int temp = arr[i];
                int j = i;

                // 插入排序
                while (j >= gap && arr[j - gap] > temp) {
                    arr[j] = arr[j - gap];
                    j -= gap;
                }

                arr[j] = temp;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};

        System.out.println("原始数组:");
        for (int num : arr) {
            System.out.print(num   " ");
        }

        shellSort(arr);

        System.out.println("n排序后数组:");
        for (int num : arr) {
            System.out.print(num   " ");
        }
    }
}

  1. 执行shellSort方法时,将传入一个整型数组arr作为参数。
  2. 取数组的长度n,然后使用初始增量gap,该增量的初始值为数组长度的一半。我们会逐渐缩小gap的值,直到它为1。这样做是为了分组进行插入排序,初始时每个分组的元素相隔较远,可以更快地将较小的元素移动到正确的位置。
  3. 使用一个外层循环来控制gap的缩小过程。在每次循环中,我们使用一个内层循环对每个子序列进行插入排序。
  4. 内层循环从gap开始,依次遍历数组中的元素。对于每个元素,我们将其保存在临时变量temp中,并使用j记录其位置。
  5. 内层循环的内部,我们使用另一个循环实现插入排序。我们通过比较jgap的差值来确定是否需要交换元素的位置。如果前一个分组的元素大于当前元素,则将前一个分组的元素移到当前位置,并将j减去gap,以便在下一次循环中继续比较。
  6. 将保存在临时变量temp中的值放置在正确的位置上,完成一次插入排序。
  7. 外层循环会重复进行,直到gap的值为1,此时进行最后一次插入排序,将整个数组排序完成。

0 人点赞