排序算法 —— 希尔排序(图文超详细)

news/2025/2/13 0:06:02/

文章目录

  • 希尔排序(直接插入排序的优化)
    • 1.分组思想
    • 2.缩小增量的过程
    • 3.排序步骤
      • 3.1 排序五组数据的情况
      • 3.2 排序两组数据的情况
      • 3.3 排序一组数据的情况
    • 4.代码分析
      • 4.1 如何设置数据组数
      • 4.2 直接插入排序实现思路
    • 5. 整体代码实现

排序算法:

1、直接插入排序

2、选择排序

3、堆排序

希尔排序(直接插入排序的优化)

希尔排序是将数据分组,将每一组进行插入排序。
每一组排成有序后,最后整体就变有序了。

1.分组思想


上图中gap为5,说明要分成5组。
这5组分别用了五种颜色的线条连接起来了。

第1组:9、4
第2组:1、8
第3组:2、6
第4组:5、3
第5组:7、5

为什么要采取上面的分组方法呢?换一种方法可以吗?
例如:挨着的元素分为一组。


如果是上面的这种分组方式的话,排序之后会变成下面的情况。



如果是最开始的分组方法的话

如果是按照最开始的分组思想分组的话,最后会排序成

可以发现左边都是叫小的数据,右边都是较大的数据。
更方便把分成的每一个组进行插入排序。

2.缩小增量的过程

前面gap为5的情况排序后会变成下面情况


按照gap把数据分成了两组。

当数据很大的时候,数据的间隔很大。
小的数据会往前方,大的数据会往后放。

gap会逐渐缩小,间隔也会逐渐缩小。

整体的数据会更加趋于有序,这个时候使用直接插入排序效率会更高。



gap为2的时候会排序成下面情况

此时分为了1组,再排序一次后变成下面情况

此时的数据即为有序的。

3.排序步骤

3.1 排序五组数据的情况

  1. gap为5,将数据分为5组,图中红色线画中的为第一组。定义一个 i 变量指向这一组的第二个数据,定义一个 j 变量指向 i - gap 的位置。
  2. 将 i 下标的值放到定义的 tmp 中,然后与 j下标 的值比较。
    若 j 下标的值较大,将 j 下标的值放到 j + gap 的位置。

    执行后:
  3. j 变量向 j - gap 位置走,若这个位置的下标为负数。
    则要将 tmp 的值放到 j + gap的位置。

    j 变量此时在-5下标处,要将 tmp 的值放到 j + 5的位置。

    这一组数据此时为有序了。
    排序下一组数据,**i++**即可,j 变量依然是在 i - gap 的位置。
    后面4组数据类似,不在演示。
    最终排序结果是:

3.2 排序两组数据的情况

  1. 此时 gap 为2,数据此时分为了两组。第一组由红色线画出(4、2、5、8、5),第二组由蓝色线画出(1、3、9、6、7)。
    i 变量指向这一组的第二个数据, j 变量指向 i - gap 的位置。

  2. 将 i 下标的值放到定义的 tmp 中,然后与 j下标 的值比较。
    若 j 下标的值较大,将 j 下标的值放到 j + gap 的位置。

    执行后:

  3. j 变量向 j - gap 位置走,若这个位置的下标为负数。
    则要将 tmp 的值放到 j + gap的位置。

    j 变量此时在-2下标处,要将 tmp 的值放到 j + 2的位置。

    这一组数据中的 2 和 4 此时为有序了。
    排序下一组数据,i++ 即可,j 变量依然是在 i - gap 的位置。
    后面剩下的数据类似,不在演示。
    最终排序结果是:

3.3 排序一组数据的情况

  1. i 变量指向第二个数据, j 变量指向 i - gap 的位置。
  2. 将 i 下标的值放到定义的 tmp 中,然后与 j下标 的值比较。
    若 j 下标的值较大,将 j 下标的值放到 j + gap 的位置。

    执行后:
  3. j 变量向 j - gap 位置走,若这个位置的下标为负数。
    则要将 tmp 的值放到 j + gap的位置。

    j 变量此时在-1下标处,要将 tmp 的值放到 j + 1的位置。

    此时 前两个数据有序了,后面的数据排序过程类似。
    排序下一组数据,i++ 即可,j 变量依然是在 i - gap 的位置。
    最终结果是:

4.代码分析

4.1 如何设置数据组数

  1. 定义 gap 将数组的长度赋值给这个变量。
int gap = array2.length;//为数组的长度 - 为10
  1. 设置循环,每次使 gap 除以2来得到5、2、1三个组。
  2. 在循环内部调用直接插入排序方法。
 while (gap > 1) {gap /= 2;//先是分成了5组,然后是2组,再是1组shell(array2, gap);//调用直接插入排序方法}

4.2 直接插入排序实现思路

  1. 遍历数组,i 变量从 gap 下标位置开始
for (int i = gap; i < array2.length ; i++){
}
  1. j 变量从 i- gap 位置开始
  int j = i - gap;
  1. j 变量要每次减去 gap 个位置,j 此时的位置要是负数就比较 j 和 tmp 的值。
for (; j >= 0; j-=gap){
}
  1. j 和 tmp 如何比较
 if (array2[j] > tmp) {//j下标的值大,将j下标的值放到j变量加上一个gap的位置上array2[j + gap] = array2[j];}else {//j下标的值较小,j下标的值要直接放到j变量加上一个gap的位置上break;}
  1. j 下标为负数的情况
 //此时j下标的值是负数了,将tmp的值放到j变量加上一个gap的位置上array2[j + gap] = tmp;

更加详细的直接插入排序讲解请参考我的另一篇文章。


文章链接:http://t.csdn.cn/rBDzh

5. 整体代码实现

 public static void shellSort(int[] array2) {int gap = array2.length;//为数组的长度 - 为10while (gap > 1) {gap /= 2;//先是分成了5组,然后是2组,再是1组shell(array2, gap);//调用直接插入排序方法}}//实现直接插入排序方法public static void shell(int[] array2, int gap) {//i下标从第一组的第二个数据开始for (int i = gap; i < array2.length ; i++) {int tmp = array2[i];//tmp存放i下标的值int j = i - gap;//j下标为i-gap个位置//j每次-gap个位置for (; j >= 0; j-=gap) {if (array2[j] > tmp) {//j下标的值大,将j下标的值放到j变量加上一个gap的位置上array2[j + gap] = array2[j];}else {//j下标的值较小,j下标的值要直接放到j变量加上一个gap的位置上break;}}//此时j下标的值是负数了,将tmp的值放到j变量加上一个gap的位置上array2[j + gap] = tmp;}}


http://www.ppmy.cn/news/824859.html

相关文章

希尔排序原理和算法图解

原理&#xff1a; 这个是基于插入排序的改进。将待排序的记录数目减少&#xff0c;所以&#xff0c;我们需要采用跳跃分割策略&#xff1a;将相距某个分量的记录组成一个子序列分别进行插入排序得到的结果是基本有序。 算法讲解&#xff1a; void ShellSort(SqList *L) {int …

希尔排序详解

一.思路 希尔排序是建立在插入排序的思想之上的&#xff0c;因为插入排序在应对数组接近有序的情况下&#xff0c;时间复杂度接近O(N)&#xff0c;故如果对数组先进行预排序&#xff0c;使数组接近有序&#xff0c;再进行直接插入排序&#xff0c;能大幅度降低时间复杂度 二.实…

排序算法——希尔排序

希尔排序 什么是希尔排序为什么不直接使用插入排序希尔排序代码实现 什么是希尔排序 希尔排序也叫做&#xff1a;缩小增量排序。 分组&#xff08;分组的组数需要循环递减&#xff0c;直到减为1&#xff09;排序。 先将待排序序列分成若干组&#xff0c;然后使用直接插入排序在…

入坑机器学习:四,单变量线性回归

开始我们机器学习的第一个算法。 还是借用吴老师的例子&#xff1a; 这个例子是预测住房价格的&#xff0c;我们要使用一个数据集&#xff0c;数据集包含俄勒冈州波特兰市的住房价格。在这里&#xff0c;我要根据不同房屋尺寸所售出的价格&#xff0c;画出我的数据集。比方说&…

C语言数据结构希尔排序(示例代码)

#include <stdio.h> #include <stdbool.h> #define MAX 7 int intArray[MAX] {4,6,3,2,1,9,7}; void printline(int count) { int i; for(i 0;i < count-1;i) { printf(“”); } printf(“\n”); } void display() { int i; printf(“[”); // navigat…

C#排序算法之希尔排序

前言 希尔排序是插入排序的优化&#xff0c;它利用了分治的思想&#xff0c;将需要排序的数组分为几段&#xff0c;在每一段中做插入排序。通过分治的思想&#xff0c;使得排序效率比起原来的插入排序要快了很多。对于插入排序&#xff0c;不了解的可以查看我之前的文章&#…

关于vue2项目搭建的步骤

vue2项目每次搭建项目总是需要注意各种插件的版本&#xff0c;在这里记录一下&#xff0c;免得总是需要看半天需要安装哪个版本。 1.创建项目 vue create 项目名称 2.安装路由插件及配置 npm i vue-router3 &#xff08;1&#xff09;router/index.jsimport VueRouter fro…

插入排序与希尔排序

插入排序 将一元素插入到已排序完毕的数组中 可以将无序数组的第一个元素看作 只有一个元素的有序数组 后将数组中的元素一一插入到有序数组中的合适位置 所有元素被插入到有序数组中时&#xff0c;便已将此数组置为有序 动图演示 代码逻辑如下&#xff1a; 以升序为例 …