一、插入排序的基本思想

  从初始有序的子集合开始,不断地把新的数据元素插入到已排列有序子集合的合适位置上,使子集合中数据元素的个数不断增多,当子集合等于集合时,插入排序算法结束。常用的 插入排序算法有直接插入排序和希尔排序两种。

  

  二、直接插入排序

  1.直接插入排序的定义

  直接插入排序的基本思想是:顺序地把待排序的数据元素按其值的大小插入到已排序数据元素子集合的适当位置。子集合的数据元素个数从只有一个数据元素开始逐次增大。当子集合大小最终和集合大小相同时排序完毕。

  2.直接插入排序的实现

    public static void straightInsertionSort(int[] L) {
int i, j, temp;
for (i = 0; i < L.length - 1; i++) {
temp = L[i+1]; // 保存要插入的数据元素
j = i;
while (j > -1 && temp <= L[j]) { // 将temp插入到原数组集合中
L[j+1] = L[j];
j--;
}
L[j+1] = temp;
}
}   int[] array1 = {9,1,5,8,3,7,4,6,2};
  初始时,子集合中L0已经排好序,即为{9}
  i=0时,temp=L1=1,j=0,0大于-1且1小于9,则L1=9,j=-1,L0=1,即将1插入到9的前面,集合中{1,9}
  i=1时,temp=L2=5,j=1,1大于-1且5小于9,则L2=9,j=0,0大于-1但5不小于1,则L1=5,集合中{1,5,9}
  i=2时,temp=L3=8,即将8和9比较,8插入到9的前面,8和5比较,不动,8和1比较,也不动,集合中{1,5,8,9}
  ...

  3.直接插入排序的性能分析

  (1)时间复杂度为O(n²)

  • 最好情况是原始数据集合已经全部排好序。这时内层while循环的循环次数每次均为0,外层for循环中每次数据元素的比较次数均为1,数据元素的赋值语句执行次数均为2。因此整个排序过程中比较次数为n-1,移动次数为2(n-1),此时的时间复杂度为O(n)。
  • 最坏情况是与原始数据集合反序排列。这时内层while循环的循环次数每次均为i,这样,整个外层for循环中的比较次数为(1+1)+(2+1)+...+(n-1+1)=(n-1)(n+2)/2,而移动次数为(1+2)+(2+2)+...+(n-1+2)=(n-1)(n+4)/2。此时的时间复杂度为O(n²)。  
  • 随机情况是数据集合中大小的排列是随机的。这时比较次数的期望和移动次数的期望均为n²/4,此时的时间复杂度为O(n²)。

  (2)空间复杂度为O(1)。

  (3)是一种稳定的排序算法。

  三、希尔排序

  1.希尔排序的定义

  希尔排序的基本思想是:把待排序的数据元素分成若干个小组,对同一小组内的数据元素用直接插入法排序;小组的个数逐次缩小;当完成了所有数据元素都在一个组内的排序后排序过程结束。希尔排序又称作缩小增量排序。

  在直接插入排序算法的性能分析中可以得出结论:原始数据集合越接近有序,直接插入排序算法的时间效率越高,其时间效率在O(n)~O(n²)之间。这个结论是希尔排序算法能够成立的基础。希尔排序算法把待排序数据元素分成若干小组,在小组内用直接插入排序算法排序,当把若干个小组合并为一个小组时,组中的数据元素集合将会接近有序,这样各组内的直接插入排序算法的时间效率就很好,最终整个希尔排序的时间效率就很高。

  2.希尔排序的实现

    public static void shellSort(int[] L, int[] d) {
int i, j, k, m, span;
int temp;
for (m= 0; m < d.length; m++) {
span = d[m];
for (k = 0; k < span; k++) {
/********将i=0换成i=k,1换成span的直接插入排序**********/
for (i = k; i < L.length - span; i = i + span) {
temp = L[i+span];
j = i;
while (j > -1 && temp <= L[j]) {
L[j + span] = L[j];
j = j - span;
}
L[j + span] = temp;
print(L);
}
/***********************************************/
}
System.out.print("span的值为" + span + "时得到的序列为: ");
print(L);
}
}

  分析代码执行过程与输出为:

int[] array1 = {9,1,5,8,3,7,4,6,2};int[] d = {4,2,1};
分析执行过程:
m=0时,span=4,k=0时,i=0,j=0时,交换9和3得到{3,1,5,8,9,7,4,6,2};i=4,j=4时,交换9和2得到{3,1,5,8,2,7,4,6,9};j=0时,交换3和2得到{2,1,5,8,3,7,4,6,9};排序{2,3,9}
m=0时,span=4,k=1时,i=1,1和7不交换,排序{1,7}
m=0时,span=4,k=2时,i=2,交换5和4,得到{2,1,4,8,3,7,5,6,9};排序{4,5}
m=0时,span=4,k=3时,i=3,交换8和6,得到{2,1,4,6,3,7,5,8,9};排序{6,8}
m=0结束,得到{2,1,4,6,3,7,5,8,9};可以发现数字1、2等小数字已经在前两位,而8、9等大数字已经在后两位,整个序列已经基本有序了。
m=1时,span=2,k=0时,排序{2,4,3,5,9}为{2,3,4,5,9}
m=1时,span=2,k=1时,排序{1,6,7,8}
m=1结束,交叉两个排序得到{2,1,3,6,4,7,5,8,9}即将之前5个和4个分别直接插入排序,然后插入到原来的位置
m=2时,span=1,k=0时,排序{2,1,3,6,4,7,5,8,9}得到{1,2,3,4,5,6,7,8,9}
输出为:
希尔排序前: 9 1 5 8 3 7 4 6 2
span的值为4时得到的序列为: 2 1 4 6 3 7 5 8 9
span的值为2时得到的序列为: 2 1 3 6 4 7 5 8 9
span的值为1时得到的序列为: 1 2 3 4 5 6 7 8 9
希尔排序后: 1 2 3 4 5 6 7 8 9

  3.希尔排序的性能分析

  (1)时间复杂度

  希尔排序增量序列的选取非常关键,需要注意的是增量序列的最后一个增量值必须是1才行。通过设置合适的增量序列,可以使得时间复杂度为O(n3/2),要好于直接插入排序的O(n²)。

  (2)空间复杂度

  希尔排序算法的空间复杂度为O(1)。

  (3)稳定性

  由于希尔排序算法是按增量分组进行的排序,两个相同的数据元素有可能分在不同的组中,所以希尔排序算法是一种不稳定的排序算法。

  

数据结构(四十六)插入排序(1.直接插入排序(O(n²)) 2.希尔排序(O(n3/2)))的更多相关文章

  1. NeHe OpenGL教程 第四十六课:全屏反走样

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. 四十六、android中的Bitmap

    四十六.android中的Bitmap: http://www.cnblogs.com/linjiqin/archive/2011/12/28/2304940.html 四十七.实现调用Android ...

  3. Android简易实战教程--第四十六话《RecyclerView竖向和横向滚动》

    Android5.X后,引入了RecyclerView,这个控件使用起来非常的方便,不但可以完成listView的效果,而且还可以实现ListView无法实现的效果.当然,在新能方便也做了大大的提高. ...

  4. “全栈2019”Java第四十六章:继承与字段

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. 第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么

    第四十六个知识点 在Sigma协议中,正确性,公正性和零知识性意味着什么 Sigma协议 Sigma协议是Alice想要向Bob证明一些东西的协议(Alice知道一些秘密).他们有下面的一般范式:Al ...

  6. abp(net core)+easyui+efcore实现仓储管理系统——入库管理之十(四十六)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  7. Deep learning:四十六(DropConnect简单理解)

    和maxout(maxout简单理解)一样,DropConnect也是在ICML2013上发表的,同样也是为了提高Deep Network的泛化能力的,两者都号称是对Dropout(Dropout简单 ...

  8. Python之路(第四十六篇)多种方法实现python线程池(threadpool模块\multiprocessing.dummy模块\concurrent.futures模块)

    一.线程池 很久(python2.6)之前python没有官方的线程池模块,只有第三方的threadpool模块, 之后再python2.6加入了multiprocessing.dummy 作为可以使 ...

  9. (四十六)c#Winform自定义控件-水波进度条-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

随机推荐

  1. java8 函数接口

    [前言] java8新特性 java8 Optional使用总结 java8 lambda表达式 Java 8 时间日期使用 1.函数式接口新特性 java8中引入了函数式接口新特性,使用@Funct ...

  2. javaweb技术入门

    JavaWeb巩固和进阶 1.如何配置外部应用? 方法一: server.xml 在<Host>中添加如下配置 <Context path="/xxx" docB ...

  3. Scala 学习笔记之集合(8) Try和Future

    import util._ import concurrent.ExecutionContext.Implicits.global import concurrent.Future import co ...

  4. web前端之浏览器: 知识汇总

    一.URL到页面 准备阶段: 输入URL,Enter进入查找 浏览器在本地查找host文件,匹配对应的IP: 找到返回浏览器并缓存 没有,则进入路由查找: 找到返回浏览器并缓存 再没有,再进入公网DN ...

  5. Android NDK(二) CMake构建工具进行NDK开发

    本文目录 一Androidstudio中需要的插件 二项目配置 ①build.gardle配置 ②CMakeLists.txt ③Android和Cpp的代码 ④so文件生成 ⑤so文件的位置 一.A ...

  6. 软件开发工具(第9章:使用Eclipse进行C/C++开发)

    一.安装MinGW MinGW是指用来生成可执行文件的编译环境,它是开发C/C++项目 的工具集.为了能够使用Eclipse CDT编译且运行C和C++程序,必须 要安装一个C/C++编译器. 下载: ...

  7. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别

    一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...

  8. 自己写的Weblogic的poc

    """ 暂时只试用于Linux,先试试用一下反弹shell CVE-2017-10271的EXp """ import requests i ...

  9. java集合类之ArrayList详解

    一.ArrayList源码分析 1.全局变量 (1)默认容量(主要是通过无参构造函数创建ArrayList时第一次add执行扩容操作时指定的elementData的数组容量为10) private s ...

  10. docker的使用 一容器命令

    Docker容器命令 前提 执行容器的前提是有镜像 . #创建并启动容器 docker run [options] images [command][args] // option 的说明 --nam ...