• 17、排序算法-希尔排序


    来源:https://www.bilibili.com/video/BV1B4411H76f?p=60

    一、思路

    希尔排序:本质还是一种插入排序,分组和之前的简单插入排序不一样,这里给出一个增量,按照这个增量进行分组,增量是逐渐减小的,减小为1时进行最后一次排序。所以希尔排序也可以叫缩小增量排序。

    例:[8,9,1,7,2,3,5,4,6,0],从小到大排列

    这里如果按照简单插入排序的话,0在一个很尴尬的位置,它需要跟所有数据进行比较,所有数据都需要后移。

    如果按照希尔排序:

    第一趟:给定一个增量gap=length/2。length是数组的长度10,所以这里的增量为5。从第一个数据开始,以增量作为步长进行分组和比较。下标0和下标5为一组进行比较,[8,3]需要交换位置;下标1和下标6为一组进行比较,[9,5]需要交换位置;下标2和下标7为一组进行比较,[1,4]不需要交换位置;下标3和下标8为一组进行比较,[7,6]需要交换位置;下标4和下标9为一组进行比较,[2,0]需要交换位置。本次比较完成后,数组变成了[3,5,1,6,0,8,9,4,7,2]。

    第二趟:gap=gap/2。这里增量为2。从第一个数据开始,下标为0、2、4、6、8的数据进行比较,即[3,1,0,9,7]进行插入排序,完成后为[0,1,3,7,9],与原来的位置一一对应;同理[5,6,8,4,2]进行插入排序,完成后为[2,4,5,6,8],与原来的位置一一对应。本次比较完成后,数组变成了[0,2,1,4,3,5,7,6,9,8]。

    第三趟:gap=gap/2。这里增量为1。从第一个数据开始,插入排序。本次比较完成后,数组变成了[0,1,2,3,4,5,6,7,8,9]。

    gap=gap/2=0。完成排序。

    二、实现

     1 //希尔排序
     2 public class ShellSort {
     3     public static void main(String[] args) {
     4         int[] arr = {8,9,1,7,2,3,5,4,6,0};
     5         System.out.println(Arrays.toString(arr));
     6 
     7         shellSort(arr);
     8         System.out.println(Arrays.toString(arr));
     9 
    10     }
    11 
    12     public static void shellSort(int[] arr){
    13         for (int gap = arr.length/2; gap > 0; gap/=2) {
    14             //从gap位置开始,后面的要依次与前面的比较(包括gap位置的数据)
    15             for (int i = gap; i < arr.length; i++) {
    16                 //按照组进行比较,不合适就交换
    17                 for (int j = i - gap; j >= 0; j-=gap) {
    18                     if(arr[j] > arr[j + gap]){
    19                         int temp = arr[j];
    20                         arr[j] = arr[j + gap];
    21                         arr[j + gap] = temp;
    22                     }
    23                 }
    24             }
    25         }
    26     }
    27 }

    结果

    [8, 9, 1, 7, 2, 3, 5, 4, 6, 0]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    这里不太好的地方就是,没有用到之前简单插入排序的思路,这里用的是交换。我们把上面的方法也叫交换式希尔排序。下面对这个排序方法进行改进,加入插入排序的思路,这里也叫移位式希尔排序

     1     public static void shellSort2(int[] arr){
     2         for (int gap = arr.length/2; gap > 0; gap/=2) {
     3             //典型的插入排序,从gap位置开始,前面的属于有序,后面的要比较(包括gap位置的数据)
     4             for (int i = gap; i < arr.length; i++) {
     5                 int insertIndex = i - gap;
     6                 int insertVal = arr[i];
     7                 while (insertIndex >= 0 && insertVal < arr[insertIndex]){
     8                     arr[insertIndex + gap] = arr[insertIndex];
     9                     insertIndex -= gap;
    10                 }
    11                 if(arr[insertIndex + gap] != i){//发生过移位操作
    12                     arr[insertIndex + gap] = insertVal;
    13                 }
    14             }
    15         }
    16     }

    测试结果与上面的一样。需要注意,这里的移位式希尔排序是我自己根据简单插入式排序改的,跟视频中讲解的有一点点不同,思路是一样的,程序中的变量名是对照前面的简单插入排序来的,我感觉这样更好理解一点。

  • 相关阅读:
    将Tue Feb 22173124 CST2022换为20220222
    curl命令
    部署高可用kafka暴露外网访问并使用go代码测试
    转发:自定义博客园cnblog主题样式Ⅱ(SimpleMemory)
    npm与cnpm切换使用
    从层序遍历构造一棵二叉树
    【ORACLE】“IMP00013: 只有 DBA 才能导入…”解决方法
    vimeasymotion操作
    fd详解
    fasd用法
  • 原文地址:https://www.cnblogs.com/zhao-xin/p/13162538.html
Copyright © 2020-2023  润新知