跟着AI学算法-排序算法-希尔排序,剖析排序过程

希尔排序(Shell Sort)是一种改进的插入排序算法,也称为“缩小增量排序”, 是非稳定排序算法。希尔排序是基于插入排序的以下两点性质而提出改进方法的:

1、插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;

2、但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;

希尔排序的基本思想是通过比较一定间隔(称为增量)的元素进行排序,并逐步减小增量,最终使整个序列变为有序。希尔排序的具体步骤如下:

1、首先确定一个增量序列(通常为n/2,n/4,...,1),然后按照这个增量序列分组。

2、对每一组使用插入排序算法进行排序。

3、逐步缩小增量,重复步骤2,直到增量为1时,排序结束。

执行过程请移步文章末尾:排序执行过程。

希尔排序的时间复杂度取决于增量序列的选取,理论上最坏情况下的时间复杂度为O(n^2),但在实际应用中,由于希尔排序的增量序列具有一定规律,因此其平均时间复杂度往往要优于简单插入排序,而且它在处理较大数据集合时比直接插入排序快得多。

AI编码实现:

本地测试:

为了能够打印排序过程,代码稍作修改。

package com.algorithm.sort;

import java.util.Arrays;

/**
 * @author LuoFei
 * @className: ShellSort
 * @projectName algorithm
 * @description: TODO
 * @date 2023/2/20 12:56
 */
public class ShellSort {

    public static void shellSort(int[] arr) {
        int n = arr.length;
        // 计算初始增量序列
        int gap = n/3;
        while (gap > 0) {
            System.out.println("增量步数:"+gap);
            //对每个增量分组使用插入排序
            for (int i= gap; i < n; i++) {
                System.out.println("第"+(i-gap+1)+"轮");
                int temp = arr[i];
                System.out.println("选择"+i+"号位数字“"+temp+"”为基准数字,与前面已排序数字比较");
                int j = i;
                //对组内元素进行插入排序
                while (j >= gap) {
                    System.out.print("比较:["+(j-gap)+", "+i+"]");
                    if (arr[j - gap] <= temp) {
                        System.out.println(", 顺序正确");
                        break;
                    }
                    System.out.println(", "+(j - gap)+" 号位后移"+gap+"位;");
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
                System.out.println("基准数字”"+temp+"“插入"+j+"号位置");
                System.out.println("新数组:"+ Arrays.toString(arr));
                System.out.println("------------------------------------------");
            }
            //缩小增量序列
            System.out.println("==========================================");
            gap /= 2;
        }
    }

    public static void main(String[] args) {
        int[] arr = {5, 2, 8, 3, 9, 1};
        System.out.println("希尔排序");
        System.out.println("初始数组:"+ Arrays.toString(arr));
        System.out.println("==========================================");
        shellSort(arr);
        System.out.print("最终数组:"+Arrays.toString(arr));
    }
}

排序执行过程:

希尔排序
初始数组:[5, 2, 8, 3, 9, 1]
==========================================
增量步数:2
第1轮
选择2号位数字“8”为基准数字,与前面已排序数字比较
比较:[0, 2], 顺序正确!
基准数字”8“插入2号位置
新数组:[5, 2, 8, 3, 9, 1]
------------------------------------------
第2轮
选择3号位数字“3”为基准数字,与前面已排序数字比较
比较:[1, 3], 顺序正确!
基准数字”3“插入3号位置
新数组:[5, 2, 8, 3, 9, 1]
------------------------------------------
第3轮
选择4号位数字“9”为基准数字,与前面已排序数字比较
比较:[2, 4], 顺序正确!
基准数字”9“插入4号位置
新数组:[5, 2, 8, 3, 9, 1]
------------------------------------------
第4轮
选择5号位数字“1”为基准数字,与前面已排序数字比较
比较:[3, 5], 3 号位后移2位;
比较:[1, 5], 1 号位后移2位;
基准数字”1“插入1号位置
新数组:[5, 1, 8, 2, 9, 3]
------------------------------------------
==========================================
增量步数:1
第1轮
选择1号位数字“1”为基准数字,与前面已排序数字比较
比较:[0, 1], 0 号位后移1位;
基准数字”1“插入0号位置
新数组:[1, 5, 8, 2, 9, 3]
------------------------------------------
第2轮
选择2号位数字“8”为基准数字,与前面已排序数字比较
比较:[1, 2], 顺序正确!
基准数字”8“插入2号位置
新数组:[1, 5, 8, 2, 9, 3]
------------------------------------------
第3轮
选择3号位数字“2”为基准数字,与前面已排序数字比较
比较:[2, 3], 2 号位后移1位;
比较:[1, 3], 1 号位后移1位;
比较:[0, 3], 顺序正确!
基准数字”2“插入1号位置
新数组:[1, 2, 5, 8, 9, 3]
------------------------------------------
第4轮
选择4号位数字“9”为基准数字,与前面已排序数字比较
比较:[3, 4], 顺序正确!
基准数字”9“插入4号位置
新数组:[1, 2, 5, 8, 9, 3]
------------------------------------------
第5轮
选择5号位数字“3”为基准数字,与前面已排序数字比较
比较:[4, 5], 4 号位后移1位;
比较:[3, 5], 3 号位后移1位;
比较:[2, 5], 2 号位后移1位;
比较:[1, 5], 顺序正确!
基准数字”3“插入2号位置
新数组:[1, 2, 3, 5, 8, 9]
------------------------------------------
==========================================
最终数组:[1, 2, 3, 5, 8, 9]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值