[算法]插入排序和希尔排序

        这里简单的介绍一下插入排序和希尔排序的算法实现,为简单起见,排序为升序且排序的数组是整形数组。

一、插入排序

(一)、算法思路

        把数组里的第一个元素视为有序的,然后取第二个元素与前面的元素作比较,如果该元素小于第一个元素,则把第一个元素往后移,第二个元素往前移,这样,我们数组前两个元素就变得有序了。接着再取第三个元素,将其与前面的元素作比较,如果该元素小于其前面的元素,则将该元素往前移,将被比较的元素往后移,然后再将该元素与前一个元素作比较,如果当该元素大于其前面的元素,那么当前该元素所在的位置就是其正确的顺序,这个时候,数组有序的序列长度增加了一,其结果就是把一个元素插入到前面的已经有序的序列当中去,所以叫做插入排序,以此重复插入排序,数组变得有序。

下面是插入排序的动图:

(二)、算法的实现 

void InsertSort(int* arr, int nums)
{for (int i = 1; i < nums; i++){int key = arr[i];//存储待插入排序的值int j;for (j = i; j > 0; j--){//依次往前作比较进行移动if (key < arr[j - 1])arr[j] = arr[j - 1];elsebreak;}//此时j的位置就是key插入排序的位置arr[j] = key;}
}

(三)、时间复杂度和稳定性

        插入排序的时间复杂度为O(n^{2})当待排序的数组为完全或接近有序时,插入排序的时间复杂度为O(n),而当待排序的数组完全或接近逆序时,插入排序的时间复杂度为O(n^{2})

        插入排序是稳定的。

二、希尔排序

        希尔排序(Shell's Sort)插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。

(一)、算法思路

        希尔排序是从插入排序上改进的,先来看看改进了什么。假如有一组数组的序列是逆序的:[10,9,8,7,6,5,4,3,2,1],那么我们的插入排序在每次插入待排序的元素时,都要以一次移动一个数据这样(增量为一)依次移动到数组的开头位置,这样时间复杂度就为O(n)了。而我们的希尔排序一开始以一个增量开始跳跃式的进行插入排序,叫做预排序将数组中较小的元素移动到数组的左边去,将数组中较大的元素移动到数组的右边去,排序一次后,数组左边差不多都是小的元素,数组的右边差不多都是大的元素。再缩小增量进行增量插入排序,跳跃进行插入排序的跳跃元素个数减小,执行该增量的插入排序,以此重复,每次执行完增量插入排序后数组的元素逐渐接近有序,当增量变为一时,执行的是朴素的插入排序,这个时候因为预排序的作用数组的元素已经非常接近有序了,执行完插入排序后,数组变为有序。

下面以缩小增量为除以2进行希尔排序来演示,假设待排序的数组为:

57210643189

增量为5:

以增量为10 / 2 = 5 分组进行增量插入排序
57210643189
对第一组红色元素进行增量插入排序
47210653189
对第二组黄色元素进行增量插入排序
43210657189
对第三组绿色元素进行增量插入排序
43110657289
对第四组蓝色元素进行增量插入排序
43186572109
对第五组紫色元素进行增量插入排序
43186572109

增量为2:

以增量为5 / 2 = 2为增量分组进行插入排序
43186572109
对第一组红色元素进行增量插入排序
13486572109
对第二组黄色元素进行增量插入排序
12436578109

增量为1:

以增量为2 / 2 = 1为增量进行朴素插入排序
12436578109
对第一组红色元素进行增量插入排序
12345678910

        我们可以看到,前两次的预排序使得最后一次的朴素插入排序非常轻松,因为待排序的数组经过预排序后变得十分接近有序了。

(二)、算法实现 

//希尔排序
void SheelSort(int* arr, int nums)
{int gap = nums;while (gap > 1){//缩小增量进行插入排序gap /= 2;//分组进行插入排序//有gap组for (int i = 0; i < gap; i++){//增量为gap的插入排序for (int j = i + gap; j < nums; j += gap){int key = arr[j]; //存储待增量插入排序的值int k;//注意这里的结束条件是k >= gap 因为要保证k - gap >= 0for (k = j; k >= gap; k -= gap){//依次往前作比较进行移动if (key < arr[k - gap])arr[k] = arr[k - gap];elsebreak;}//此时k的位置就是key插入的位置arr[k] = key;}}}
}

上面的代码有三个循环嵌套,我们还可以使其变得简单点。

        我们可以在每次进行增量插入排序时,i从0遍历到nums - gap - 1的位置,然后依次将其遍历的位置的以增量为单位的下一个元素key进行增量插入排序

比如上面的:

以增量为5 / 2 = 2为增量分组进行插入排序
43186572109

我们可以这样进行增量插入排序:

i = 0

将key = 1 插入到有序序列 4 中

结果:

 

i = 1

key = 8 插入到有序序列 3 中

结果:

 

 

i = 2

key = 6 插入到有序序列 1 4 中

结果:

i = 3

key = 5 插入到有序序列 3 8 中

结果:

i = 4

key = 7 插入到 有序序列 1 4 6 中

结果不变

 i = 5 

key = 2 插入到有序序列 3 5 8 中

结果:

i = 6

key =10 插入到 有序序列 1 4 6 7 中

结果不变 

i = 7

key = 9 插入到有序序列 2 3 5 8 9 中

结果不变:

12436578109

这就是通过从头遍历实现执行一次预排序的过程。

具体代码如下:

void SheelSort(int* arr, int nums)
{int gap = nums;while (gap > 1){gap /= 2;for (int i = 0; i < nums - gap; i++){int j;int key = arr[i + gap];//存储待插入排序的值for (j = i; j >= 0; j -= gap){if (key < arr[j])arr[j + gap] = arr[j];elsebreak;}//此时j + gap的位置为key插入的位置arr[j + gap] = key;}}
}

(三)、时间复杂度和稳定性

        希尔排序的时间复杂度比较复杂,大概为O(n^{1.3-2}),其排序算法不稳定。

        上面的代码中的缩小增量为除以2,其实还可以是其他值,如 3 4 5 .....,只要保证最后一次可以执行增量为1的朴素插入排序即可,如当缩小增量的倍率为3时,gap = gap / 3 + 1。

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

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

相关文章

【秋招笔试题】小Q的树

解析&#xff1a;分析易得走过的路中至多存在一个分叉&#xff0c;则维护每个结点接下来的路的最大值与次大值然后相加即可。 #include <iostream> #include <vector> #include <algorithm> using namespace std; #define int long long const int MAXN 1…

ESD防护之电容妙用

谈到ESD防护&#xff0c;应用最广泛的是ESD/TVS管&#xff0c;对于正负4KV的pin脚不上电ESD测试&#xff0c;也可以仅仅依靠nf级电容完成ESD防护。下面以一篇实际案例进行说明。 实验要求&#xff1a;正负4KV对产品connector的Pin脚进行ESD测试&#xff0c;connector中的地脚接…

栈和队列<数据结构 C版>

目录 栈&#xff08;Stack&#xff09; 栈的结构体 初始化 销毁 入栈 判空 出栈 取栈顶元素 获取栈个数 测试&#xff1a; 队列&#xff08;Queue&#xff09; 队列的结构体 单个结点 队列 初始化 销毁 入队列&#xff0c;队尾 判空 出队列&#xff0c;队头 …

Spring Cloud微服务项目统一封装数据响应体

在微服务架构下&#xff0c;处理服务之间的通信和数据一致性是一个重要的挑战。为了提高开发效率、保证数据的一致性及简化前端开发&#xff0c;统一封装数据响应体是一种非常有效的实践。本文博主将介绍如何在 Spring Cloud 微服务项目中统一封装数据响应体&#xff0c;并分享…

二市在度低开,连续11个交易日低开,后市如何走?

今天的A股&#xff0c;让人愣住了&#xff0c;你知道是为什么吗&#xff1f;盘面上出现2个耐人寻味的重要信号&#xff0c;一起来看看&#xff1a; 1、今天两市再度低开&#xff0c;连续11个交易日低开&#xff0c;让很多人愣住了。别慌&#xff01;汽车、军工板块大涨&#x…

MYSQL存储引擎InnoDB, MyISAM简介

MYSQL存储引擎 在开始谈到mysql存储引擎之前&#xff0c;我们应该知道或者了解存储引擎是什么&#xff0c;存储引擎是为了解决什么样的问题的。 在mysql中&#xff0c;存储引擎是处理不同表类型SQL操作的MySQL组件&#xff0c;同时MySQL服务器采用可插拔的存储引擎架构&#x…

XLua 原理分析 三

前面已经介绍了Lua与C#的基础通信原理&#xff0c;和Wrap中间文件的作用。有了前面2篇的基础&#xff0c;大概已经能搞清这块的原理。 为了加深对这块的印象&#xff0c;这里开始正式分析Xlua中的Lua和C#的通信。 一、Lua如何调用CS的过程 lua的初始化代码&#xff1a; pri…

乌班图下的vscode粘贴代码后一直在输入CTRLV命令

最近在VMware中使用vscode开发c程序中&#xff0c;拷贝一段代码后&#xff0c;代码界面一直输入CTRLV命令&#xff0c;导致乌班图桌面死掉&#xff0c;无法操作、 解决方法&#xff1a; 1、强制重启。长按电源按钮强制关机&#xff0c;然后再次开机。 2、使用命令行界面。同时…

1.ESP32-CAM 下使用 ESP-IDF 打开摄像头

主要资料&#xff1a; 乐鑫官方编程指南 ESP-IDF 编程指南安信可官方模块页 安信可-ESP32-CAM摄像头开发板官方使用教程 安信可ESP32-CAM摄像头开发demo–局域网拍照、实时视频、人脸识别 &#xff08;开发环境是Linux&#xff09; 本文目标是在 Windows 下跑通摄像头 hello …

快手电商Android一面凉经(2024)

快手电商Android一面凉经(2024) 笔者作为一名双非二本毕业7年老Android, 最近面试了不少公司, 目前已告一段落, 整理一下各家的面试问题, 打算陆续发布出来, 供有缘人参考。今天给大家带来的是《快手电商Android一面凉经(2024)》。 面试职位: Android工程师 技术一面 面试形式…

python count返回什么

描述 count() 方法用于统计字符串中某个子字符串出现的次数&#xff0c;可选参数为开始搜索与结束搜索的位置索引。 语法 count() 方法语法&#xff1a; S.count(sub[,start0[,endlen(S)]]) 参数 sub -- 搜索的子字符串。 S -- 父字符串。 start -- 可选参数&#xff0c;…

【数据结构】哈希表的模拟实现

文章目录 1. 哈希的概念2. 哈希表与哈希函数2.1 哈希冲突2.2 哈希函数2.3 哈希冲突的解决2.3.1 闭散列&#xff08;线性探测&#xff09;2.3.2 闭散列的实现2.3.3 开散列(哈希桶)2.3.4 开散列的实现 2.4 开散列与闭散列比较 1. 哈希的概念 在我们之前所接触到的所有的数据结构…

FastAPI(八十一)实战开发《在线课程学习系统》接口开发-- 推荐课程列表与课程点赞

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 推荐课程列表 逻辑很简单 点赞数 > 500 那么符合要求的课程是&#xff1a; def get_like_course(db: Session):"""获取推荐课程…

一番赏小程序搭建,线上一番赏市场

一番赏作为一个经久不衰的潮流市场&#xff0c;一直流行于消费者市场中。一番赏商品拥有不同系列&#xff0c;涵盖了热门动漫、漫画、影视等主题&#xff0c;商品包含了手办等周边商品&#xff0c;具有非常大的收藏价值。相比于其他潮玩模式&#xff0c;一番赏的性价比更高&…

Kylin 入门教程

Apache Kylin 是一个开源的分布式数据仓库和 OLAP(在线分析处理)引擎,旨在提供亚秒级查询响应时间,即使在处理超大规模数据集时也是如此。Kylin 可以有效地将原始数据预计算为多维数据立方体(Cube),并利用这些预计算结果来提供快速查询。本文将带你从基础知识到操作实践…

GC(垃圾收集)简析:为什么Java需要它?

GC&#xff08;垃圾收集&#xff09;简析&#xff1a;为什么Java需要它&#xff1f; 1、什么是GC&#xff1f;2、为什么Java需要GC&#xff1f;3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、什么是GC&#xff1f; GC&#xff…

黄果树瀑布

早上我们按计划6点吃饭&#xff0c;可是酒店没水了&#xff0c;等我们吃完饭已经近七点 &#xff0c;到景区已经7点多了。景区入口的人特别多&#xff0c;验过包裹&#xff0c;只刷脸就进去了。排队坐大巴&#xff0c;向左是陡坡塘和七星桥。 第一站陡坡塘&#xff0c;服务中心…

synergy Ubuntu 18 和Windows 配置

下载链接 Windows 版本 https://altushost-swe.dl.sourceforge.net/project/synergy-stable-builds/v1.8.8-stable/synergy-v1.8.8-stable-Windows-x64.msi?viasf1Ubuntu 18 版本 sudo apt-get install synergy配置方式 我这边配置需求是 笔记本电脑&#xff08;Windows系统…

为什么用LeSS?

实现适应性 LeSS是一个产品开发的组织系统&#xff0c;旨在最大化一个组织的适应性。关于适应性&#xff08;或者敏捷性&#xff0c;也就是敏捷开发的初衷&#xff09;我们是指优化&#xff1a; 以相对低的成本改变方向的能力&#xff0c;主要是基于通过频繁交付产生的探索。从…

基于微信小程序的搬家服务系统(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 涉及技术栈&#xff1a;SpringBoot、Vue、SSM、H…