讨厌算法的程序员 1 - 插入排序

讨厌算法的程序员系列入口

什么是算法

在说插入排序之前,我们了解下《算法导论》对算法的从两种不同角度的定义。

一般性解释:

算法是定义良好的计算过程,它取一个或一组值作为输入,并产生出一个或一组值作为输出。

基于应用的解释:

算法是一种工具,用来解决一个具有良好规格说明的计算问题。该问题的描述可以用通用的语言,来规定所需的输入/输出关系。与之对应的算法则描述了一个特定的计算过程,用于实现这一输入/输出关系。

后一种解释在告诉我们,我们不必对于每个问题都去重新设计、证明和实现算法,而是有能力将实际问题转换成已知算法问题,然后选取合适的解法。而这种能力就是学习算法的目的所在。这要求我们不仅要积累算法知识,还要在更高的抽象层次上理解算法的方法论。

排序问题的形式定义

排序问题是算法要解决的一个基本问题。它的形式化定义如下:

输入:n个数的一个序列[a1, a2, ..., an]。

输出:输出序列的一个排列[a1', a2', ..., an'], 满足a1' ≤ a2' ≤ ... ≤ an'。

插入排序算法

插入排序算法,对于少量元素的排序问题,是一个有效的算法。

经典应用

扑克

即便是玩过扑克牌的小孩子,其实都对插入排序算法了然于胸。

  • 摸牌之前,所有将会被你摸到的牌,此时是一种乱序的状态。
  • 你开始摸牌,并将新摸到的牌插入到合适的位置,以保证你手中的牌总是有序的。
  • 直到摸到最后一张,将其插入到合适的位置,此时你手中所有的牌就已经排好序了。

算法的抽象表达

想让计算机听懂上述的算法,需要将其进行翻译。

INSERTION-SORT(A)
1 for j = 2 to A.length
2   key = A[j]
3   // Insert A[j] into the sorted sequence A[1..j-1].
4   i = j - 1
5   while i > 0 and A[i] > key
6       A[i + 1] = A[i]
7       i = i - 1
8   A[i + 1] = key

原著中的伪码无可挑剔,就沿用了。做一些说明:

  • 算法名称INSERT-SORT;
  • A是一个长度为n的要排序的数组,用A.length表示n;
  • 把待排序数组A逻辑上分为两个数组,排好序的(手中的牌),未排序的(桌上待摸的牌);
  • 排好序的数组起始只有一个元素,就是原数组A的第一个元素(摸出的第一张牌无需排序),循环变量用i表示;
  • 未排序的数组起始,从原数组A的第二个元素一直到最后一个元素,所以外层的遍历是“2 to A.length”,循环变量用j表示;
  • 外层遍历过程中,每个当前元素A[j]都暂存至key变量中;
  • key要加入排序好的数组,会从该排序好数组的最末i(j-1)开始进行比较,如果A[i]大于key,A[i]移动到A[i+1],i自减,继续与key比较,如果此时i ≤ 0 或者 A[i] ≤ key,循环条件不成立跳出,将key存入A[i+1]。

算法工作例子

插入算法如何工作

说明:

  • (a)~(e)是循环迭代,(f)是最终排好的数组;
  • 数组上方是数组的下标;
  • 黑色块表示每次外层迭代,待插入左侧数组的数A[j];
  • 灰色块表示参与和A[j]比较的数;
  • 黄色箭头是伪码第6行表达的移动;
  • 蓝色大箭头是伪码第8行表达的移动;

Java实现

public class InsertionSort {
    public static void sortInASC(int[] numbers){
        for(int j = 1; j < numbers.length; j++){
            int key = numbers[j];
            int i = j - 1;
            while(i >= 0 && numbers[i] > key){
                numbers[i + 1] = numbers[i];
                i = i - 1;
            }
            numbers[i + 1] = key;
        }
    }
}

InsertSort.java下载

上一篇 0 前言
下一篇 2 证明算法的正确性


共享协议:署名-非商业性使用-禁止演绎(CC BY-NC-ND 3.0 CN)
转载请注明:作者黑猿大叔(简书)

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

推荐阅读更多精彩内容