前几章讲了选择排序中的直直接选择排序、双向选择排序、堆排序,这次来讲讲利用‘插入’为核心来实现的插入排序算法。

插入排序

把待排序的记录按其关键码值的大小逐个插入到一
个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

其实在我们的生活中,插入排序是随处可见的

例如打扑克牌时我们将发来的卡牌一张一张的插入进排序好的手牌中。整理图书或者档案时按照编号将新的书籍放入已排序号的书架。这就是插入排序的核心 “将未排序数据一个个插入进已排序的数据中


直接插入排序

直接插入排序就是对这个思路的简单应用,例如对于下面这个数据,对其排升序。

int arr[] = {46, 74, 53, 14, 26, 36, 86, 65, 27, 34};

如果要理解一个排序算法,我们首先要理解他的一趟思路。

对于上面这个数据,因为我们要排升序,按照前面的思路我们需要将未排序数列插入进已排序数列。红框框起来的地方就是按照升序排序好的序列,此时,因为74的下一个数据53比他小,所以我们要将他插入进这个已排序的数列中,并且在已排序的数列中找到合适的位置。


因为53比74小,所以往前移动, 然后46比53小,所以在46前停下,然后将74放到原本53的位置,形成新的有序数据。

第二趟

然后因为14比74小,将其插入进有序数列中,因为14比有序数列中的任何数都小,所以通过比较大小,然后被放到了数组最前端,然后将74放到原本14的位置。

总结下来就是将数列中已经排好的有序子串以此与后面的对比,然后将其插入到合适的位置。

这是一趟的思路,而多趟无非就是不断重复这个过程,直到排序结束。因为排N个数据,所以最坏情况下只需将n-1个数据插入就可以排序成功。

所以下面开始代码实现

void InsertSort(int* arr, int n)
{int i, end, temp;for(i = 0; i < n - 1; i++){end = i;temp = arr[end + 1];//将插入元素保存下来, 从有序子串的尾部开始对比插入while(end >= 0){if(arr[end] > temp){arr[end + 1] = arr[end];end--;//如果插入的数据比这个位置的数据大,则比该数据大的数据后移,插入数据继续往前直到找到比他小得数据后停下}elsebreak;}arr[end + 1] = temp;//将插入的元素放到最终所在的位置}
}


每趟排序

直接插入排序
时间复杂度:平均情况:O(n) 最好情况O(n^2) 最坏情况O(n^2)
空间复杂度:O(1)


希尔排序

希尔排序是对直接插入排序的改进,也是最高效的插入排序。
他的核心就是一种分组预排序的思路:

1.预排序
2.直接插入排序

就是用gap分组预排序,再对每一组插入排序

什么意思呢?希尔排序引入了一个变量,gap(步长),将间隔为gap的元素分为一组,对每一组进行插入排序,然后不停减少gap的大小,既每次扩大分组,在部分有序的基础上再次进行分组插入排序,知道gap=1也就是只剩下一个分组时,排序完成

还是刚刚那些数据

int arr[] = {46, 53, 74, 14, 26, 36, 86, 65, 27, 34};
关于gap的选择

gap越大,越不接近有序,跳的越快
gap越小,越接近有序,跳的越慢

为了刚开始快速预排,所以一开始我们需要将gap设置大一点,实现部分有序,然后逐渐减少,实现全体有序。

一般gap = length / 3 + 1;

还是那句老话,理解排序首先理解单趟。

为了方便观看我将所有分组按照颜色不同来划分

首先46大于间隔gap的26,将这个分组内的26插入到46前。
下面同理

然后到交换后的46也就是第5个位置时,将27插入到子序列,26 ,46中的合适位置。
下面同理

说白了,就是对每一个gap间隔的分组进行插入排序,在将每个相同颜色的子序列都排成有序,就是这一趟的目的。


这就是第一趟全部跑完后的结果,所有颜色的子序列已经全部有序

第二趟
gap = 2

还是上面的思路,每一种颜色对应的子序列排序。

排完后

最后一趟 gap = 1
没有间隔,对所有数据进行插入排序,因为数据已基本有序,所以这一趟会特别快


排序结果

下面来进行代码实现

void ShellSort(int* arr, int n)
{int gap = n, i;//当gap = 1时说明只剩下一组,并且最后一组已排序,数组排序结束while(gap > 1){gap = gap / 3 + 1;//每趟减少gapfor(i = 0; i < n - gap; ++i){int end = i;int temp = arr[end + gap];  while(end >= 0){if(arr[end] > temp){ arr[end + gap] = arr[end];            end -= gap;}elsebreak; } arr[end + gap] = temp;}     }
}

上面的代码和直接插入排序极为相似,因为底层的核心思想还是直接插入排序,只需要将原来的步长1改为gap即可实现,当外层gap=1时说明内层gap为1的分组已经排序结束,数组已有序。

全部排序

希尔排序
时间复杂度:平均情况:O(n) 最好情况O(n^1.3) 最坏情况O(n^2)
空间复杂度:O(1)

数据结构与算法 | 直接插入排序、希尔排序相关推荐

  1. Hark的数据结构与算法练习之希尔排序

    算法说明 希尔排序是插入排序的优化版. 插入排序的最坏时间复杂度是O(n2),但如果要排序的数组是一个几乎有序的数列,那么会降低有效的减低时间复杂度. 希尔排序的目的就是通过一个increment(增 ...

  2. java数据结构排序实验报告_java数据结构与算法之插入排序详解

    本文实例讲述了java数据结构与算法之插入排序.分享给大家供大家参考,具体如下: 复习之余,就将数据结构中关于排序的这块知识点整理了一下,写下来是想与更多的人分享,最关键的是做一备份,为方便以后查阅. ...

  3. C语言——十四种内部排序算法【直接插入排序-冒泡排序-选择排序-插入排序-希尔排序-归并排序-快速排序-堆排序-折半插入排序-二分查找-路插入排序-表插入排序-简单选择排序-直接选择排序-树形选择】

    目录: 一:插入排序 A:直接插入排序 1.定义: 2.算法演示 实例1: 3.基本思想 4.排序流程图 实例1: B:希尔排序 1.定义: 2.算法演示 实例2: C:其他插入排序 a:折半插入排序 ...

  4. 数据结构与算法:十大排序算法之插入排序

    数据结构与算法:十大排序算法之插入排序 package TopTenSortingAlgorithms;import java.util.Arrays; import java.util.Scanne ...

  5. 【排序算法】冒泡排序|选择排序|插入排序|希尔排序

    文章目录 冒泡排序 选择排序 插入排序 希尔排序 冒泡排序   第一个元素开始向第二个元素比较,若大于则交换位置,不大于则不动.然后第二个元素和第三个元素比较,再然后第三个元素和第四个元素比较-一直比 ...

  6. python程序结构有哪几种_Python数据结构与算法(几种排序)小结

    Python数据结构与算法(几种排序) 数据结构与算法(Python) 冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺 ...

  7. 《数据结构与算法》实验:排序算法实验比较——选择排序 堆排序

    <数据结构与算法>实验和课程Github资源 <数据结构与算法>实验:线性结构及其应用--算术表达式求值 <数据结构与算法>实验:树型结构的建立与遍历 <数据 ...

  8. 直接插入排序 希尔排序 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 基数排序的算法分析和具体实现 ...

    排序分为内部排序和外部排序 内部排序是把待排数据元素全部调入内存中进行的排序. 外部排序是因数量太大,把数据元素分批导入内存,排好序后再分批导出到磁盘和磁带外存介质上的排序方法. 比较排序算法优劣的标 ...

  9. 数据结构与算法之插入排序

    数据结构与算法之插入排序 目录 插入排序介绍 插入排序思路分析 代码实现 1. 插入排序介绍 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的. 2. 插 ...

  10. 插入排序(折半查找优化插入排序||希尔排序) _清风明月

    插入排序:插入排序分为三个步骤: 1. 找位置.(序列可分为两个部分,第一个部分是有序序列,其二是非有序序列.当为有序序列时,查找可以改进为折半查找,优化算法速度.) 2. 移动. 3. 插入.查找的 ...

最新文章

  1. 想法2: 充电性冰袋
  2. 图灵赠书——程序员12月书讯
  3. 获取当前应用程序的文件名
  4. iOS Hacker 越狱后开发和逆向工具准备
  5. text type dropdown list - INIT_DATA
  6. java 中violate_Java中的Volatile关键字
  7. Windows编程—Windows驱动开发环境搭建
  8. 实战解析丨如何对Mysql连接请求的tcpdump内容进行分析
  9. 爬虫如何监听插件_NodeJS概述2-事件插件-简易爬虫
  10. android 布局圆变椭圆,Android实现自定义圆形、圆角和椭圆ImageView(使用Xfermode图形渲染方法)...
  11. java手写map,手写 RxJava ---- map 操作符
  12. fatfs 文件属性_FATFS文件系统剖析(全).
  13. CrossPHP 1.5.5 发布了
  14. spring源码之@dependsOn
  15. 无主3局域网找不到服务器,无主之地3局域网模式设置方法攻略 无主之地3局域网怎么用...
  16. 使用 PyTorch 检测眼部疾病
  17. 管理工作三大忌!推荐阅读收藏哦
  18. 性能测评:腾讯云轻量服务器4核8G12M带宽流量CPU主频型号
  19. c语言丢手帕,题手帕原文_李希圣古诗_古诗文网
  20. 压缩Gradle构建 (Squeezing your Gradle builds)

热门文章

  1. springboot整合servlet
  2. Redis分布式快速入门
  3. Spring AOP源码解析(三)—— AOP引入(续)
  4. 简述中断处理的6个步骤_实用!处理电机振动的11个常用步骤
  5. liunxC下零碎知识点的总结
  6. Excel 2016新增函数之TEXTJOIN
  7. MySQL多个相同结构的表查询并把结果合并放在一起的语句(union all)
  8. JSP常见的三个编译指令
  9. 韩国研制出世界最薄光伏电池:厚度仅为人类头发直径百分之一
  10. ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态