详解十大经典排序算法(四):希尔排序(Shell Sort)

news2024/9/30 1:39:39

算法原理

希尔排序是一种基于插入排序的排序算法,也被称为缩小增量排序。它通过将待排序的序列分割成若干个子序列,对每个子序列进行插入排序,然后逐步缩小增量,最终使整个序列有序。

算法描述

希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。它是插入排序的一种更高效的改进版本。希尔排序的核心思想是将原始数据分成多个子序列,先对每个子序列进行插入排序,然后逐步减少子序列的数量,最终对整个数据序列进行插入排序。

这个算法的关键特点是其间隔序列的选择,即每次排序时元素之间的间隔。开始时,间隔较大,随着算法的进行,间隔逐渐减小,最后间隔为1,即普通的插入排序。通过这种方式,希尔排序可以快速减少大量的初期乱序,从而提高排序效率。

希尔排序的步骤如下:

  1. 选择合适的间隔序列:最初的版本使用序列长度的一半作为第一个间隔,然后逐步减半,直到间隔为1。现代版本可能会使用不同的间隔序列。

  2. 分组并排序:按照当前间隔将数组分为多个子序列,独立地对每个子序列应用插入排序。

  3. 减少间隔并重复:减少间隔大小,重复上述过程,直到间隔减至1。

  4. 最终排序:当间隔减至1时,进行一次标准的插入排序,此时由于序列已经部分排序,这一步骤会非常快。

动画演示

在这里插入图片描述

代码实现

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

        //设置排序的间隔(gap)。
        //初始间隔设置为数组长度的一半,每次循环后间隔减半。
        //循环继续直到间隔减至0。
        for (int gap = n / 2; gap > 0; gap /= 2) {

            //内层循环从gap开始,对数组进行遍历。
            for (int i = gap; i < n; i += 1) {
                int temp = arr[i];//存储当前元素的值。
                int j;//用于后续的内嵌循环,用于比较和交换元素。

                //此循环用于将较大的元素向右移动。
                //当j大于等于gap且arr[j - gap](当前元素的前一个间隔位置的元素)大于temp(当前元素)时,将arr[j - gap]向右移动到arr[j]的位置。
                for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                    arr[j] = arr[j - gap];
                }
                //此处的j 是上面循环 j -= gap 后的。
                arr[j] = temp;
            }
        }


    }

算法复杂度

时间复杂度(最坏)时间复杂度(最好)时间复杂度(平均)空间复杂度稳定性
O(n^2)O(nlogn)O(n^1.5)O(1)不稳定
  • 最好情况:O(nlogn)
  • 平均情况:取决于间隔序列。对于原始的间隔序列(减半序列),平均时间复杂度为O(n^1.5)。
  • 最坏情况:取决于间隔序列。对于某些不佳的间隔序列,最坏情况可以达到O(n^2)。
  • 空间复杂度:O(1)。希尔排序是一种原地排序算法。

希尔排序的优化方式

<<<前方高能 量力而行>>>

希尔排序的性能在很大程度上依赖于间隔序列的选择。不同的间隔序列会导致算法的性能有显著差异。优化希尔排序通常涉及使用更有效的间隔序列,而不是初始版本中的简单递减序列(如数组长度的一半递减至1)。以下是几种常见的优化方法:

  1. 优化间隔序列
  • Hibbard序列:使用形式为 2^k - 1 的间隔,如 1, 3, 7, 15, 31, … 这样的序列可以使希尔排序达到大约 O(n^(3/2)) 的时间复杂度。

  • Sedgewick序列:这是一种更复杂的间隔序列,可以进一步优化性能。一个常见的Sedgewick序列是 1, 5, 19, 41, 109, …

  • Knuth序列:使用形式为 (3^k - 1) / 2 的间隔,如 1, 4, 13, 40, 121, …

这些序列都是试图在排序过程中更有效地打乱数组,从而避免某些特定情况下的糟糕性能。

  1. 动态间隔

一种更高级的优化是根据数组的特定特征动态选择间隔。这种方法通常适用于特定类型的数据或在需要极致优化时使用。

下面是一个使用Hibbard间隔序列的希尔排序的Java实现示例:

 public static void sort(int[] arr) {
        int n = arr.length;
        int h = 1;

        // 计算最大间隔
        while ((h * 2) - 1 < n) {
            h = h * 2;
        }
        h = h - 1;

        // 希尔排序
        while (h >= 1) {
            for (int i = h; i < n; i++) {
                int temp = arr[i];
                int j;
                for (j = i; j >= h && arr[j - h] > temp; j -= h) {
                    arr[j] = arr[j - h];
                }
                arr[j] = temp;
            }
            h = (h + 1) / 2 - 1; // 更新间隔为下一个较小的Hibbard数
        }
    }

这段代码首先计算最大的Hibbard间隔,然后在每次迭代中减小间隔,直到间隔为1。每个间隔都会对数组进行一轮希尔排序。这种使用Hibbard间隔的方法通常比简单的递减间隔方法表现得更好。


相关概念
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1283577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软考S01计算机系统知识】E01 中央处理单元

E01 中央处理单元 计算机系统硬件基本组成中央处理单元组成功能 多核 CPU 计算机系统硬件基本组成 计算机系统由硬件和软件组成&#xff0c;基本硬件系统由 运算器、控制器、存储器、输入设备 和 输出设备 5大部件组成&#xff1b; 中央处理单元&#xff1a; 运算器、控制器等…

【MySQL语言汇总[DQL,DDL,DCL,DML]以及使用python连接数据库进行其他操作】

MySQL语言汇总[DQL,DDL,DCL,DML] SQL分类1.DDL:操作数据库&#xff0c;表创建 删除 查询 修改对数据库的操作对表的操作复制表&#xff08;重点&#xff09;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 2.DML:增删改表中数据3.DQL&#xff1a;查询表中的记录…

hnust 湖科大 创业基础考察课程结课作业 创业计划书+路演PPT 资源下载

hnust 湖科大 创业基础考察课程结课作业 创业计划书 资源下载 资源详尽&#xff0c;图文并茂&#xff0c;开箱即用&#xff0c;附赠若干模板 资源预览图 创业计划书word 路演PPT 赠品 下载链接 链接&#xff1a;https://pan.baidu.com/s/1p1n6qwM5Jx6bB96ifAJmiw?pwd1111 …

Autosar MCAL-RH850P1HC Port配置

文章目录 PortPortGroupPortPin PortFilterGroupConfigDigital Filter Clock Selection0Digital Filter Clock Selection1 PortGeneralCritical Section ProtectionDev Error DetectDevice NameMax ModeSet Pin Default Modee ApiSet Pin Modee ApiSet to Dio Alt Modee ApiUse…

Ubuntu22.04 交叉编译mp4V2 for Rv1106

一、配置工具链环境 sudo vim ~/.bashrc在文件最后添加 export PATH$PATH:/opt/arm-rockchip830-linux-uclibcgnueabihf/bin 保存&#xff0c;重启机器 二、下载mp4v2 下载路径&#xff1a;MP4v2 | mp4v2 三、修改CMakeLists.txt 四、执行编译 mkdir build cd buildcmak…

ubuntu16.04升级openssl

Ubuntu16.04 默认带的openssl版本为1.0.2 查看&#xff1a;openssl version 1.下载openssl wget https://www.openssl.org/source/openssl-1.1.1.tar.gz 编译安装 tar xvf openssl-1.1.1.tar.gz cd openssl-1.1.1 ./config make sudo make install sudo ldconfig 删除旧版本 su…

springboot的常用注解

声明解释这个对象&#xff08;类或者其他&#xff09;组件相关 名称作用Controller用于修饰MVC中controller层的组件SpringBoot中的组件扫描功能会识别到该注解&#xff0c;并为修饰的类实例化对象&#xff0c;通常与RequestMapping联用&#xff0c;当SpringMVC获取到请求时会…

DistributionBalancedLoss

Distribution-Balanced Loss P I ( x k ) P^I(x^k) PI(xk) 1 C ∑ y i k 1 1 n i {1\over C}\sum\limits_{y_i^k1}{1\over{n_i}} C1​yik​1∑​ni​1​&#xff0c; P i C ( x k ) P^C_i(x^k) PiC​(xk) 1 C 1 n i {1\over C}{1\over{n_i}} C1​ni​1​ r i k _i^k ik​ P i …

目标检测——R-CNN系列检测算法总结

R-CNN系列算法详细解读文章&#xff1a; R-CNN算法解读SPPNet算法解读Fast R-CNN算法解读Faster R-CNN算法解读Mask R-CNN算法解读 目录 1、概述1.1 获取目标候选框1.2 候选框提取特征1.3 候选框分类及边框回归 2、R-CNN系列算法概述2.1 R-CNN算法2.2 SPPNet算法2.3 Fast R-CN…

C++作业5

完成沙发床的多继承&#xff08;有指针成员&#xff09; 代码&#xff1a; #include <iostream>using namespace std;class Bed { private:double *money; public:Bed(){cout << "Bed::无参构造函数" << endl;}Bed(double money):money(new doub…

http代理如何设置手机上网?http代理起到了哪些作用

本文将详细介绍如何设置手机上网使用HTTP代理&#xff0c;以及HTTP代理所起到的作用。 一、HTTP代理是什么&#xff1f; HTTP代理是一种网络协议&#xff0c;它允许客户端与服务器之间进行数据传输。它是一种常用的代理服务&#xff0c;可以帮助用户通过HTTP协议访问被封锁的网…

帆软报表不能增加SAP连接方式 通过插件一致性检测 同步至本地解决

帆软报表开发人员需要增加一个SAP数据连接方式&#xff1a;SAP_ECC_600环境 在服务器端不能直接增加&#xff0c;而在帆软报表设计器切换到远程模式时&#xff0c;又不能显示SAP连接&#xff0c;导致不能增加。 解决&#xff1a;重新进入帆软报表报计器时报以下错误&#xff0c…

Spring Cloud + Vue前后端分离-第2章 使用Maven搭建SpringCloud项目

第2章 使用Maven搭建SpringCloud项目 Maven两大核心功能&#xff1a; 依赖管理&#xff08;Jar包管理&#xff09; 构建项目&#xff08;项目打包&#xff09; 使用Eureka搭建注册中心 使用spring initializr创建spring cloud项目 SpringCloud和Maven简介 SpringBoot和Spr…

FacetWP Relevanssi Integration相关性集成插件

点击阅读FacetWP Relevanssi Integration相关性集成插件原文 FacetWP Relevanssi Integration相关性集成插件是FacetWP与用于高级搜索的 Relevanssi 插件的集成显着增强了您网站的搜索功能。这个强大的工具使您的用户能够轻松找到他们寻求的特定内容&#xff0c;无论他们的查询…

craco + webpack 4 升 5

craco webpack 4 升 5 更新包版本尝试build升级其他依赖库使用process插件打印进度信息到底需要多少内存分析构建产出添加 splitChunk总结记录一些好文章&#xff1a; 我的项目使用 craco react 开发 我的 package.json {// ......"dependencies": {"ant-desi…

如何在 Chrome 上调试文件打断点

1. 控制台进入 Source 2. CtrlP 输入文件名称 3. 在需要的位置手动打断点 4. 重新触发代码运行&#xff0c;触发断点

【android开发-14】android中fragment用法详细介绍

1&#xff0c;fragment是什么&#xff1f; Fragment是Android中的一种组件&#xff0c;它在Android 3.0&#xff08;API级别11&#xff09;及以后的版本中引入。Fragment可以用来在Activity中添加一个或多个具有自己的用户界面的片段。它们可以与Activity进行交互&#xff0c;并…

查找一维向量中大于或小于某一值的所有连续片段

文章目录 经常会遇到一种场景&#xff0c;那就是有一个一维向量&#xff0c;我们要找到其中所有大于设定阈值的片段。就好比电路中有高代电平&#xff0c;我们要找连续的高电平段或低电平&#xff1a; 如上图&#xff0c;我们只要标红的高电平&#xff0c;对应代码&#xff1…

【原神游戏开发日志1】缘起

【原神游戏开发日志1】缘起 版权声明 本文为“优梦创客”原创文章&#xff0c;您可以自由转载&#xff0c;但必须加入完整的版权声明 文章内容不得删减、修改、演绎 相关学习资源见文末 大家好&#xff0c;最近看到原神在TGA上频频获奖&#xff0c;作为一个14年经验的游戏开…