java 实现排序算法之「插入排序」

java 实现排序算法系列

这是 Java 实现排序算法的第三篇文章——插入排序算法。插入排序可以说成是「一类」简单的排序算法,因为插入排序可以有变种,比如二分查找插入排序算法,本文讲述的是直接插入排序。

如文中出现错误,请在公众号「ikook」聊天窗口留言,十分感谢。

插入排序

插入排序「Insertion Sort」是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

来看一下插入排序算法的思路:

  • 将需排序的数据分成已排序和未排序两部分,从第一个元素开始,并将该元素看做已排序。

  • 取得下一个元素,即第二个元素,在已排序的序列中由后向前扫描,找出合适的位置将该元素插入。

  • 重复上述步骤,直到最后一个元素被插入到已排序序列中。

  • 排序完成。

使用插入排序为一列数字进行排序的过程示意图(来自维基百科):

<center>



</center>

插入排序算法示意图(来自维基百科):

<center>



</center>

代码实现

从上面可以看到,算法思路非常简单,但是代码就不那么简单易写了。算法本身是没有问题的,之所以不易写我觉得是由于编程语言的问题。这里我们使用 Java 来实现,那就拿 Java 来讲。

在上述思路中我们可以提出几个问题,先来看下。首先,我们该如何判断合适的位置?边界条件该怎么处理?在数组中插入元素,必然会移动数据,如何控制数据的移动?

为了解决这些问题,我们可以在算法思路的第二步做手脚,将第二步细化。我们不在已排序的序列起始位置开始比较,从已排序序列的尾部开始逆序比较,只要比待插入的数据大,那就向后移动,直到不大于该数据,此时空出来的位置就放入待插入数据。

上代码:

private static void insertionSort(int[] arr){
      for (int i=1; i<arr.length; i++){
          int value = arr[i];
          int position=i;
          while (position>0 && arr[position-1]>value){
              arr[position] = arr[position-1];
              position--;
          }
          arr[position] = value;
      }
}

如果在代码的理解上遇到困难,可以利用 IDE 的调试功能来学习。如下图(IntelliJ IDEA):

<center>



</center>

算法复杂度

从上述内容容易看出,无论输入的数据怎样,插入排序算法总会进行 n-1 次排序。

由于每个元素插入点的不确定性,该算法复杂度并不是一定的。假设我们要将 n 个元素的序列升序排序,这时存在最好情况和最坏情况。

最好情况就是,序列已经是升序排列了(即数据本身的顺序和我们需要的顺序相同)。此时,需要进行的比较操作需(n-1)次即可,时间复杂度为 O(n)。

最坏情况很显然,序列为逆序排列时,即降序排序时为最坏。此时,需要进行的比较共有 1/2n(n-1) 次,时间复杂度为 O(n^2)。

平均来说,插入排序算法复杂度为 O(n^2)。插入排序的赋值操作是比较操作的次数加上(n-1)次。

空间复杂度,插入排序所有的数据移动均在内部进行,唯一的开销是我们使用了一个临时变量,则空间复杂度为 O(1)。

插入排序算法分析

算法稳定性:
拿本文中的例子来讲,只需要找到需插入元素的位置即可,并不需要交换,则直接插入排序是稳定排序算法。

适用场景:
从算法复杂度可以看出,该排序算法不适合数据较大的情况,数量级小于千时,插入排序是一个不错的选择。在 STL 的 sort 算法和 stdlib 的 qsort 算法中,都将插入排序作为快速排序的补充,用于少量数据的排序。

其他

关于插入排序算法的变种大家有兴趣的自己 Google 一下,本文只讲述了基本的直接插入排序。插入排序的变种大概有这几种:二分查找插入排序、2 - 路插入排序、表插入排序。二分查找插入排序有的文献叫做折半插入排序,2 - 路插入排序和表插入排序可以参考《数据结构》(严蔚敏、吴伟民著)一书。

完。

相关阅读:
Java 实现「冒泡排序」
Java 实现「选择排序」

PS:如果你觉得本文对你有一点帮助,点赞、转发,不胜感激。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的...
    Luc_阅读 2,213评论 0 35
  • 排序的基本概念 在计算机程序开发过程中,经常需要一组数据元素(或记录)按某个关键字进行排序,排序完成的序列可用于快...
    Jack921阅读 1,361评论 1 4
  • 该系列文章主要是记录下自己暑假这段时间的学习笔记,暑期也在实习,抽空学了很多,每个方面的知识我都会另起一篇博客去记...
    Yanci516阅读 12,067评论 6 19
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,101评论 0 52
  • 这周话题是有关贵人的,于是很多朋友把注意力放到了“如何遇到贵人”上。 还记得这句话吗? 自己首先是个贵人,才能遇到...
    pws019阅读 155评论 0 0