直接插入排序与希尔排序的详解及对比

目录

1.直接插入排序(至少有两个元素才可以使用)

        排序逻辑

B站动画演示:直接插入排序

逻辑转为代码:

稳定性:稳定

时间复杂度:O(N^2)

空间复杂度:O(1)

应用场景

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

希尔排序(也叫缩小增量排序)定义

预排序

逻辑转为代码

时间复杂度

稳定性:不稳定


1.直接插入排序(至少有两个元素才可以使用)

        排序逻辑

排序方式其实就是从第一个元素开始插入,把接下来要插入的元素放在当前集合的合适的位置。

有点云里雾里,没事看下面例子,我来演示一遍。

对arr{8 5 7 2 1 4 3}排升序为例(排降序逻辑是一样的,只是比较方式,恰好相反):

事前,需要定义三个变量:

1.两个int类型的下标指向两个元素,分别是:

               endIndex(在最开始,指向数组第二个元素,也就是5)

               con(在最开始,指向数组首元素)

注意:排序过程中,小标区间[0,con]所指向的元素集合永远都是有序的

2.一个int类型的变量tmp,用来存“挖出来的”元素


前2个元素排序:

因为5已经被tmp存起来了,所以可以假想5这个元素,被挖了出来(当然此时他还存在与数组):

        

三个变量都起到了应有的功能,可以开始排序了:

        如果tmp<arr[con],那么arr[con+1]=arr[cont]

         然后con++

如图:

此时con==-1了,说明“前两个元素已经排好了”

只需要把tmp的值给到arr[con+1]即可。

如图:

好了,可以更新endIndex/tmp/con,然后进行前3个元素排序

con=endIndex

endIndex++

tmp=arr[endIndex]

如图:

快看!直接插入排序会保证区间[0,con]一定有序!


前3个元素排序:

在上图中,如果tmp<arr[con]

则执行同样的操作:

arr[con+1]=tmp

con--

如图

此时,出现了新的情况

tmp不在小于arr[con]了

说明“前3个元素排序已经完成”

arr[con+1](元素本来是8)=tmp(赋值成7)

如图:

然后就可以调整endIndex/tmp/con,进行前4个元素排序:

快看!直接插入排序会保证区间[0,con]一定有序!

一下的排序直接用图演示,逻辑和前面一样:

前4个元素排序:

让arr[con+1]=tmp,然后进行前5个元素排序:

进行前6个元素排序:

此时tmp>arr[con],说明,"已经排序好了",直接赋值arr[con+1]=tmp:

如上图,最后一次排序你来试试?

B站动画演示:直接插入排序

逻辑转为代码:

class InsertSort {

    public void insert(int[] arr) {
        if (arr.length == 1) return;//只有一个元素,可以直接返回,因为一个数字,就是有序的
        int tmp = 0;//用来存放endIndex所指向的元素
        for (int endIndex = 1; endIndex < arr.length; endIndex++) {
            tmp = arr[endIndex];
            int con = endIndex - 1;
            for (; con >= 0; con--) {
                if (tmp < arr[con]) {
                    arr[con + 1] = arr[con];
                }else{//如果tmp>=arr[con]说明已经排序完成(区间[0,con]),只要arr[con+1]=tmp即可
                    break;
                }
            }
            arr[con + 1] = tmp;
        }
    }
}

稳定性:稳定

时间复杂度:O(N^2)

在最坏的情况,就是

需要排升序,但是所给的数组刚好是降序,反之亦然。

此时,从第二个元素开始排序,那么时间复杂度就===

1+2+3+.......+N-1(排列N-1次,每次都要走完已经排列好的数组)

简化一下==

1+2+3+4....+N=N(1+N)/2=(N+N^2)/2=O(N^2)

空间复杂度:O(1)

没什么好说的

应用场景

根据直接插入排序的排序特点,如果一个序列越接近有序,那么直接插入排序的时间复杂度就越小。

所以:

当前有一组数据 基本上趋于有序 那么就可以使用直接插入排序

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

如标题所讲,希尔排序与直接插入排序有千丝万缕的关系。

事实也的确如此。

我们在前直接插入排序的应用场景一节讲过:直接插入排序在接近有序时,时间会快很多。

所以,有一个叫希尔(Shell)的大神就想到了这样一个办法:

        先对数组进行预排序了,然后在使用直接插入排序,时间不就得到了优化吗?

希尔排序(也叫缩小增量排序)定义

先选定一个整数,把待排序文件中所有记录分成多个组, 所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达 =1时,所有记录在同一组内排好序。

预排序

其实就是定义里所说的分成多个组,对每一个组中的元素进行排序即可。

如图:

gap/=2----直到gap为1(就是纯的直接插入排序了)

观察一下,上面的数组是不是非常接近有序了?

此时gap/=2就是1,也就是对整个数组进行直接插入排序,那么排序速度就可以变得很快了。

逻辑转为代码

class Shell {

    public void shellSort(int[] arr) {
        int gap = arr.length-1;//这里gap初始值,直接给到整个数组的长度
        while (gap > 0) {
            shell(arr, gap);
            gap /= 2;//每次减少一半的间隔
        }
    }

    private void shell(int[] arr, int gap) {//此方法,就十分类似直接插入排序了,基本就是把1换成gap
        for (int i = gap; i < arr.length; i+=gap) {
            int tmp = arr[i];
            int j = i - gap;
            for (; j >= 0; j -= gap) {//往数组前面比较
                if (tmp < arr[j]) {//交换,然后继续往前面比较
                    arr[j + gap] = arr[j];
                }else{
                    //当前这一组数”已经有序了“
                    break;
                }
            }
            arr[j + gap] = tmp;//把坑填上
        }
    }
}

时间复杂度

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排 序的时间复杂度都不固定(下面图片有兴趣可以看):

《数据结构-用面向对象方法与C++描述》--- 殷人昆

讲了那么多我们来提炼一下:

希尔排序时间复杂度不好算,这里的gap不好取,涉及到当今没有解决的数学难题,但是大概范围可以给到:

O(N^(1.25))到O(1.6*N^1.25)

稳定性:不稳定

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VUE父组件向子组件传递值

创作灵感 最近在写一个项目时&#xff0c;遇到了这样的一个需求。我封装了一个组件&#xff0c;这个组件需要被以下两个地方使用&#xff0c;一个是搜索用户时用到&#xff0c;一个是修改用户信息时需要用到。其中&#xff0c;在搜索用户时&#xff0c;可以根据姓名或者账号进…

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

【Unity】苹果(IOS)开发证书保姆级申请教程

前言 我们在使用xcode出包的时候&#xff0c;需要用到iOS证书(.p12)和描述文件(.mobileprovision) 开发证书及对应的描述文件用于开发阶段使用&#xff0c;可以直接将 App 安装到手机上&#xff0c;一个描述文件最多绑定100台测试设备 1.证书管理 进入网站Apple Developer &…

从虚拟化走向云原生,红帽OpenShift“一手托两家”

汽车行业已经迈入“软件定义汽车”的新时代。吉利汽车很清醒地意识到&#xff0c;只有通过云原生技术和数字化转型&#xff0c;才能巩固其作为中国领先汽车制造商的地位。 和很多传统企业一样&#xff0c;吉利汽车在走向云原生的过程中也经历了稳态业务与敏态业务并存带来的前所…

视频美颜SDK原理与实践:从算法到应用

当下&#xff0c;从社交媒体到视频通话&#xff0c;人们越来越依赖于视频美颜功能来提升自己的形象。而视频美颜SDK作为支撑这一技术的重要工具&#xff0c;其原理和实践至关重要。 一、什么是视频美颜SDK&#xff1f; 视频美颜SDK是一种软件开发工具包&#xff0c;用于集成到…

FloodFill算法---DFS

目录 floodfill算法概念&#xff1a; 算法模板套路&#xff1a; 例题1&#xff1a;图像渲染 例题2&#xff1a;岛屿数量 例题3&#xff1a;岛屿的最大面积 例题4&#xff1a;被围绕的区域 floodfill算法概念&#xff1a; floodfill算法是一种常用的图像处理算法&#xf…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

云主机修复监控插件异常的方法

首先&#xff0c;进入云监控服务--选择主机监控&#xff0c;勾选上网络配置异常的云主机&#xff0c;最上面的修复插件配置&#xff0c;然后等待大约半个小时多&#xff0c;再观察下主机的状态。 一般情况下问题都可以被解决&#xff0c;如果解决不了&#xff0c;可以尝试卸载…

剑指 Offer 03.:数组中重复的数字

剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。…

Linux下的进程管理:创建、终止、切换与等待

文章目录 一、引言二、进程创建1、进程创建的概念与场景2、进程创建的方式a、fork() 系统调用b、fork() 后的执行流程 3、进程创建的过程a、进程创建过程b、子进程创建过程 4、父子进程关系与属性继承 三、进程终止1、进程终止的原因2、进程的错误码和退出码a、错误码b、退出码…

Golang基础5-指针、结构体、方法、接口

指针 和c/c类似&#xff0c;但是go语言中指针不能进行偏移和运算&#xff0c;安全指针 &&#xff08;取地址) *(根据地址取值) nil(空指针&#xff09; make和new之前对比&#xff1a;make用于初始化slice&#xff0c;map&#xff0c;channel这样的引用类型 而new用于类…

热知识:更多团队采用3个及以上内部开发者平台

01 介绍 根据 Perforce Puppet 的一份新报告中&#xff0c;平台工程的采用已经在一些企业内看到了成效&#xff0c;78% 的受访者表示他们的组织拥有专门的平台团队至少三年了。 然而&#xff0c;这并不意味着这些组织只使用同一套工具。四分之三的调查参与者表示&#xff0c;他…

如何使用SOLIDWORKS添加装饰螺纹线规格

在我们的设计过程中&#xff0c;有很多的时候螺纹规格在机械设计手册上没有&#xff0c;而我们的SOLIDWORKS软件里面录制的都是符合标准的的螺纹&#xff0c;至于其他的特种或者超出的规格需要我们设计人员去手工添加&#xff0c;以下介绍我们装饰螺纹线新规格的添加方法&#…

关于PMO卓越中心职能建设的实践与思考︱PMO大会

全国PMO专业人士年度盛会 浪潮电子信息产业股份有限公司PMO时军先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“让组织持续卓越——关于PMO卓越中心职能建设的实践与思考”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; …

菜单访问url/接口url为什么要带时间戳

一&#xff0c; 问题 1&#xff0c;菜单url中如果不加时间戳&#xff0c;会导致什么问题。我们现在做一个东西&#xff0c;需要获取菜单的访问地址&#xff0c;我们要拼这个地址 2&#xff0c;查询接口中&#xff0c;时间戳&#xff0c;如果不加&#xff0c;具体导致什么问题 二…

Vue集成three.js,加载glb、gltf类型的3d模型

安装基本依赖 // 注意OrbitControls要加{}&#xff0c;注意路径是jsm import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls.js’; // import { dat } from ‘three/examples/jsm/controls/dat.gui.js’; // dat gui这个插件&#xff0c;是另外自己下载…

杰理使用USB声卡模式时关闭MIC

杰理在使用PC模式的时候&#xff0c;想只保留扬声器&#xff0c;但不要打开MIC功能&#xff0c;可以配置USB_DEVICE_CLASS_CONFIG中把MIC_CLASS去掉&#xff0c;然后重新编译就可以了。

Kimi 高效使用技巧,80%的人都不知道

关注我, AI 学习之旅上&#xff0c;我与您一同成长&#xff01; 一、引言 Kimi 作为国产之光&#xff0c;在过去的一个多月里成为国内大模型的香饽饽。据数据分析&#xff0c;Kimi 网页、APP、小程序等各端的日活已经突破 300 万&#xff0c;超过文心一言、通义千问、智谱清言…

单链表实现通讯录

不过多赘述了 顺序表的增删查改-CSDN博客https://blog.csdn.net/bkmoo/article/details/137566495?spm1001.2014.3001.5502 使用顺序表实现通讯录-CSDN博客https://blog.csdn.net/bkmoo/article/details/137676561?spm1001.2014.3001.5502这里没有使用文件操作只是简单的使…