讨厌算法的程序员 1 - 插入排序
时间:2022-05-08
本文章向大家介绍讨厌算法的程序员 1 - 插入排序,主要内容包括什么是算法、排序问题的形式定义、插入排序算法、算法的抽象表达、算法工作例子、Java实现、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
什么是算法
在说插入排序之前,我们了解下《算法导论》对算法的从两种不同角度的定义。
一般性解释:
算法是定义良好的计算过程,它取一个或一组值作为输入,并产生出一个或一组值作为输出。
基于应用的解释:
算法是一种工具,用来解决一个具有良好规格说明的计算问题。该问题的描述可以用通用的语言,来规定所需的输入/输出关系。与之对应的算法则描述了一个特定的计算过程,用于实现这一输入/输出关系。
后一种解释在告诉我们,我们不必对于每个问题都去重新设计、证明和实现算法,而是有能力将实际问题转换成已知算法问题,然后选取合适的解法。而这种能力就是学习算法的目的所在。这要求我们不仅要积累算法知识,还要在更高的抽象层次上理解算法的方法论。
排序问题的形式定义
排序问题是算法要解决的一个基本问题。它的形式化定义如下:
输入: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下载。
- 终结 finalize()和垃圾回收(garbage collection)
- 代码+实战:TensorFlow Estimator of Deep CTR —— DeepFM/NFM/AFM/FNN/PNN
- 【SSH测试整合Demo】企业人事管理系统
- Hybris 项目工程配置
- 购物车案例【简单版】
- 再学习之MyBatis.
- 用户登陆注册【JDBC版】
- 学习思考之《编程之美》.
- 干货 | 深度剖析服务发现组件Netflix Eureka
- 多线程编程学习一(Java多线程的基础).
- TensorFlow | 自己动手写深度学习模型之全连接神经网络
- 多线程编程学习二(对象及变量的并发访问).
- ASM基本配置问题(r5笔记第89天)
- 如何上手使用 Facebook 的开源平台 Detectron?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法