一、插入排序的基本思想

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

  

  二、直接插入排序

  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. 注解在Java中是如何工作的

    来一点咖啡,准备好进入注解的世界. 注解一直是 Java 的一个非常重要的部分,它从 J2SE 5.0 开始就已经存在了.在我们的应用程序代码中,经常看到 @Override 和 @Deprecate ...

  2. 『嗨威说』算法设计与分析 - STL中Sort函数的实现原理初探

    本文索引目录: 一.对Sort算法实现的个人阅读体会 二.Sort算法使用的三个排序算法的优点介绍 2.1 插入排序的优缺点 2.2 堆排序的优缺点 2.3 快速排序的优缺点 2.4 新的结合排序—— ...

  3. 略学扩展Eculid算法

    扩展 Euclid 算法 Euclid 算法 辗转相除法 计算两个数最大公因数 \(\text{gcd}(a,\,b) = \text{gcd}(b,\,a\%b)\) exEuclid 算法 裴蜀定 ...

  4. gym102201E_Eat Economically

    题意 给\(2n\)个物品,分别有\(a,b\)属性,对于\(i=1...n\),选择\(i\)个\(a\)属性和\(i\)个\(b\)属性,且每个物品只能作为一种属性的贡献,求最小的值. 分析 看了 ...

  5. 读《深入理解Elasticsearch》点滴-查询二次评分

    理解二次评分 二次评分是指重新计算查询返回文档中指定个数文档的得分,es会截取查询返回的前N个,并使用预定义的二次评分方法来重新计算他们的得分 小结 有时候,我们需要显示查询结果,并且使得页面上靠前文 ...

  6. linux常用开发命令总结

    linux常用命令 文件操作命令 1. cd 目录名/目录名  切换目录 cd .. 切换到上一级目录  (change dictionary) Ctrl+C强制退出命令行,回到上一级 2.ls    ...

  7. passwd、shadow、group文件格式

    [root@bogon ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash 登录名:密码占位符:UID:GID:注释:家目录:用户的默认shell ...

  8. python的__name__ == \'__main__\' 意义

    转自http://www.jb51.net/article/51892.htm 很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码 ...

  9. 集合查询表--Map

    查询表 Map接口java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构成为Map.我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存放valu ...

  10. JavaSE----01.Java简介

    01.Java简介 1.java介绍     Java是于1995年由Sun公司推出的一种跨平台.面向对象的高级程序设计语言.Java最初的名字叫OAK.Java是一种通过解释方式来执行的语言,其语法 ...