写在前边

大家好,我是melo,一名大二上软件工程在读生,经历了一年的摸滚,现在已经在工作室里边准备开发后台项目啦。

不过这篇文章呢,还是想跟大家聊一聊数据结构与算法,学校也是大二上才开设了数据结构这门课,希望可以一边学习数据结构一边积累后台项目开发经验。

最近我们进入了排序算法专题,上节课聊到了"简单"插入排序,那在简单的基础上,我们可以怎么做进一步的优化呢,这篇来看看优化版--希尔排序

知识点

概念

希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。

希尔排序又称缩小增量排序,因 DL.hell 于 1959 年提出而得名。

它通过比较相距一定间隔的元素来进行,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。

引入

简单插入排序存在问题

改进

  • 分割待排序记录的个数,分别进行插入排序

基本思想

  • 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止

精髓

  • 由于开始时每组只有很少整数,所以排序很快。之后每组含有的整数越来越多,但是由于这些数也越来越有序,所以排序速度也很快。

示意图

按一定增量分组,然后逐渐减小增量

初始化gap为length/2,逐渐减小为gap/2,直到gap不满足>0的条件

分组后,再对该组进行简单插入排序

  • 拿图中的第三步举例,数组分成了两组[3,1,0,9,7],[5,6,8,4,2]

    • 对[3,1,0,9,7]进行简单插入排序,看成前n-1个为有序数组,第n个为待插入的元素(找到自己的位置后插入即可)

不够清晰的话也可以看下边这张



代码实现

力扣912排序数组 : https://leetcode-cn。com/problems/sort-an-array/submissions/

又是这道题hhh,万能

思路概览

首先

  • 我们要先初始化增量gap=length/2,然后不断缩小gap=gap/2 直到不满足gap>0

所以我们最外层会需要一个for循环来调控这个gap的变化

其次,再往内层走

  • 对于分组后,由于我们是要对分组后的每一组进行简单插入排序,而插入排序我们默认从待排序数组的第二位开始,所以我们需要从每一组的第二位开始去遍历,直到整个数组的末尾

for循环让i=gap;i<数组;i++即可

最后,就对该数组进行插入排序即可

  • 注意不是跟前一个进行比较了,而是跟 j-gap 比较

最初版本(for)

for的话,我是先把j赋值等于i-gap,这样的话就是跟j去比较,最后也还会去j-=gap

会导致我最后跳出循环的时候,得插到j+gap

/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortArray(int* nums, int numsSize, int* returnSize){
//逐步缩小增量gap
for(int gap=numsSize/2;gap>0;gap=gap/2){
int insertValue = 0;
int j;
//从分组后的第一组的第二位开始
for(int i=gap;i<numsSize;i++){
//保存待插入的值
insertValue=nums[i];
//因为本身有序,若待插入的数还大于最后一个数,则无须继续遍历下去了
//注意j>=0的条件,这里无哨兵了
for(j=i-gap;j>=0 && insertValue<nums[j];j-=gap){
//若待插入的值小于索引值,证明要索引值需要后移,空出j这个位置给插入值
nums[j+gap]=nums[j];
}
//跳出循环后,把这个数插入到指定位置
nums[j+gap]=insertValue;
}
}
*returnSize=numsSize;
return nums;
}

改进for

先去判断是否 j-gap>=0,满足才进循环,才会去j-=gap,所以最后j就是要插入的位置

/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* sortArray(int* nums, int numsSize, int* returnSize){
//逐步缩小增量gap
for(int gap=numsSize/2;gap>0;gap=gap/2){
int insertValue = 0;
//用于插入排序中遍历待排序的数组
int j;
//从分组后的第一组的第二位开始
for(int i=gap;i<numsSize;i++){
//保存待插入的值
insertValue=nums[i];
//因为本身有序,若待插入的数还大于最后一个数,则无须继续遍历下去了
for(j=i;j-gap>=0 && insertValue<nums[j-gap];
j-=gap){
//若待插入的值小于索引值,证明要索引值需要后移,空出j这个位置给插入值
nums[j]=nums[j-gap];
}
//跳出循环后,把这个数插入到指定位置
nums[j]=insertValue;
}
}
*returnSize=numsSize;
return nums;
}

注意

  • 希尔排序没有办法用到哨兵了,我们需要注意判断是否走到头了

参考

  • 菜鸟教程
  • 尚硅谷数据结构与算法

"简单"的优化--希尔排序也没你想象中那么难的更多相关文章

  1. 【PHP数据结构】插入类排序:简单插入、希尔排序

    总算进入我们的排序相关算法的学习了.相信不管是系统学习过的还是没有系统学习过算法的朋友都会听说过许多非常出名的排序算法,当然,我们今天入门的内容并不是直接先从最常见的那个算法说起,而是按照一定的规则一 ...

  2. Fragment中监听onKey事件,没你想象的那么难。

    项目中越来越多的用到Fragment,在用Fragment取代TabHost的时候遇到了一个问题,我们都知道,TabHost的Tab为Activity实例,有OnKey事件,但是Fragment中没有 ...

  3. php六种基础算法:冒泡,选择,插入,快速,归并和希尔排序法

    $arr(1,43,54,62,21,66,32,78,36,76,39); 1. 冒泡排序法  *     思路分析:法如其名,就是像冒泡一样,每次从数组当中 冒一个最大的数出来.  *     比 ...

  4. 算法(第四版)学习笔记之java实现希尔排序

    希尔排序思想:使数组中随意间隔为h的元素都是有序的. 希尔排序是插入排序的优化.先对数组局部进行排序,最后再使用插入排序将部分有序的数组排序. 代码例如以下: /** * * @author seab ...

  5. 数据结构和算法(Golang实现)(22)排序算法-希尔排序

    希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...

  6. 【PHP数据结构】其它排序:简单选择、桶排序

    这是我们算法正式文章系列的最后一篇文章了,关于排序的知识我们学习了很多,包括常见的冒泡和快排,也学习过了不太常见的简单插入和希尔排序.既然今天这是最后一篇文章,也是排序相关的最后一篇,那我们就来轻松一 ...

  7. c++实现排序(简单插入,希尔,选择,快速,冒泡,堆排)

    简单插入排序 适用于记录较少且基本有序的记录.算法思想:给定一个存在分界线的序列,分界线左边有序,右边无序,依次将右边的没排序的数与左边序列进行比较,插入相应位置,再对分界线做出相应调整,下面用图来说 ...

  8. 常见排序算法总结:插入排序,希尔排序,冒泡排序,快速排序,简单选择排序以及java实现

    今天来总结一下常用的内部排序算法.内部排序算法们需要掌握的知识点大概有:算法的原理,算法的编码实现,算法的时空复杂度的计算和记忆,何时出现最差时间复杂度,以及是否稳定,何时不稳定. 首先来总结下常用内 ...

  9. Python实现八大排序(基数排序、归并排序、堆排序、简单选择排序、直接插入排序、希尔排序、快速排序、冒泡排序)

    目录 八大排序 基数排序 归并排序 堆排序 简单选择排序 直接插入排序 希尔排序 快速排序 冒泡排序 时间测试 八大排序 大概了解了一下八大排序,发现排序方法的难易程度相差很多,相应的,他们计算同一列 ...

随机推荐

  1. java 小算法

    //鸡兔同笼 20个头 58腿 for(int a=0;a<=20;a++) { int b = 20-a; if((2*b+4*a)==58) { System.out.println(a+& ...

  2. sqlalchemy ————关联表

    1.创建模型的时候做外键关联 class UI_ID(db.Model): __tablename__ = 'ui_id' id = db.Column(INTEGER(11), primary_ke ...

  3. 动图图解GC算法 - 让垃圾回收动起来!

    原创:码农参上(微信公众号ID:CODER_SANJYOU),欢迎分享,转载请保留出处. 提到Java中的垃圾回收,我相信很多小伙伴和我一样,第一反应就是面试必问了,你要是没背过点GC算法.收集器什么 ...

  4. P7324-[WC2021]表达式求值【dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P7324 题目大意 给一个只包含\(m\)个值的表达式,\(<\)表前后取最小值,\(>\)表前后取最大 ...

  5. (一):细说贝叶斯滤波:Bayes filters

    认知计算,还要从贝叶斯滤波的基本思想讲起,本文主要是对<Probabilistic Robotics>中贝叶斯滤波器部分的详细讲解. 这一部分,我们先回顾贝叶斯公式的数学基础,然后再来介绍 ...

  6. MySQL强人“锁”难《死磕MySQL系列 三》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 前言 最近数据库 ...

  7. 在昨天夜黑风高的晚上,我偷了隔壁老王的Python入门课件,由浅入深堪称完美!

    隔壁老王是一个资深码农,就业教育事业的秃顶之才昨天我下楼打酱油,看他迎面走来,满目春光我好奇的问道:老王,有什么好事,隔壁小花叫你上门了吗?老王:秘密!!我心想:哎呦~不错啊半晚之时,连猫狗都睡着了, ...

  8. 宝塔Linux面板搭建与安全狗安装(WEB服务器搭建与WAF安装)

    环境 系统:CentOS 7.3 (64位) 软件: 宝塔Linux 7.7 网站安全狗Linux-Apache版V2.3.18809(64位) 宝塔面板 下载和安装 网址:https://www.b ...

  9. CORS+XSS的漏洞利用payload

    之前有人问我有没有CORS+XSS的利用姿势,翻了一下国内貌似都没有利用姿势于是就写了这篇文章!!! 首先找到一个反射xss,然后使用xss加载javascript代码达到跨域劫持目的payload如 ...

  10. 【JAVA】【作业向】第一题:本学期一班级有n名学生,m门课程。现要求对每门课程的成绩进行统计:平均成绩、最高成绩、最低成绩,并统计考试成绩的分布律。

    1.预备知识:动态数组Array实现: 2.解题过程需要理解的知识:吧唧吧唧吧唧吧唧 不想做了 就用了最简单的方法 和c语言类似 java版本 `import java.util.Scanner; / ...