使用插入排序为一列数字进行排序的过程
**插入排序**（英語：）是一种简单直观的排序算法。它的工作原理是通过构建有序序列，对于未排序数据，在已排序序列中从后向前扫描，找到相应位置并插入。**插入排序**在实现上，通常采用in-place排序（即只需用到{\displaystyle O(1)}的额外空间的排序），因而在从后向前扫描过程中，需要反复把已排序元素逐步向后挪位，为最新元素提供插入空间。

記載
--

最早擁有排序概念的機器出現在1901至1904年間由赫爾曼·何樂禮發明出使用基數排序法的分類機，此機器系統包括打孔，制表等功能，1908年分類機第一次應用於人口普查，並且在兩年內完成了所有的普查數據和歸檔。
赫爾曼·何樂禮在1896年創立的分類機公司的前身，為電腦製表記錄公司（CTR）。他在電腦製表記錄公司曾擔任顧問工程師，直到1921年退休，而電腦製表記錄公司在1924年正式改名為IBM。

概述
--

Insertion Sort 和打撲克牌時，從牌桌上逐一拿起撲克牌，在手上排序的過程相同。

舉例：

輸入： {5 2 4 6 1 3}。

首先拿起第一張牌, 手上有 {5}。

拿起第二張牌 2, 把 2 insert 到手上的牌 {5}, 得到 {2 5}。

拿起第三張牌 4, 把 4 insert 到手上的牌 {2 5}, 得到 {2 4 5}。

以此類推。

算法
--

一般来说，**插入排序**都采用in-place在数组上实现。具体算法描述如下：

1. 从第一个元素开始，该元素可以认为已经被排序
2. 取出下一个元素，在已经排序的元素序列中从后向前扫描
3. 如果该元素（已排序）大于新元素，将该元素移到下一位置
4. 重复步骤3，直到找到已排序的元素小于或者等于新元素的位置
5. 将新元素插入到该位置后
6. 重复步骤2~5

範例程式碼
-----

此范例程序以C语言实现。

```
void insertion\_sort(int arr[], int len){
 int i,j,key;
 for (i=1;i!=len;++i){
 key = arr[i];
 j=i-1;
 while((j>=0) && (arr[j]>key)) {
 arr[j+1] = arr[j];
 j--;
 }
 arr[j+1] = key;
 }
}

```

此范例程序以Objective C实现。

```
- (NSMutableArray \*)insertionSort:(NSArray \*)array {
 NSMutableArray \*sortArray = [array mutableCopy];
 NSNumber \*key = @(0);
 int j = 0;
 for (int i = 1; i < sortArray.count; i++) {
 key = array[i];
 j = i - 1;
 while ((j >= 0) && [sortArray[j] integerValue] > [key integerValue]) {
 sortArray[j + 1] = sortArray[j];
 j --;
 }
 sortArray[j + 1] = key;
 }
 return sortArray;
}

```

### Julia (程式語言)

```
# Julia Sample : InsertSort
function InsertSort(A)
 for i=2:length(A)
 key = A[i]
 j=i-1
 while (j>=1)&&(A[j]>key)
 A[j+1]=A[j]
 j-=1
 end
 A[j+1]=key
 end
 return A
end

# Main Code
A = [16,586,1,31,354,43,3]
println(A) # Original Array
println(InsertSort(A)) # Insert Sort Array

```

算法复杂度
-----

如果目标是把n个元素的序列升序排列，那么采用**插入排序**存在最好情况和最坏情况。最好情况就是，序列已经是升序排列了，在这种情况下，需要进行的比较操作需{\displaystyle n-1}次即可。最坏情况就是，序列是降序排列，那么此时需要进行的比较共有{\displaystyle {\frac {1}{2}}n(n-1)}次。**插入排序**的赋值操作是比较操作的次数减去{\displaystyle n-1}次，（因为{\displaystyle n-1}次循环中，每一次循环的比较都比赋值多一个，多在最后那一次比较并不带来赋值）。平均来说**插入排序**算法复杂度为O(n^{2})。因而，**插入排序**不适合对于数据量比较大的排序应用。但是，如果需要排序的数据量很小，例如，量级小于千；或者若已知輸入元素大致上按照順序排列，那么**插入排序**还是一个不错的选择。
插入排序在工业级库中也有着广泛的应用，在STL的sort算法和stdlib的qsort算法中，都将插入排序作为快速排序的补充，用于少量元素的排序（通常为8个或以下）。

参考文献
----

1. 1 2  Cormen, Thomas H.（英语：）; Leiserson, Charles E.（英语：）; Rivest, Ronald L.; Stein, Clifford..  3rd. MIT Press and McGraw-Hill. 2009: 16–18 [1990]. ISBN 0-262-03384-4. .

延伸閱讀
----

|  |  |
| --- | --- |
|  | 維基教科書中的相關電子：**算法实现/排序/插入排序** |

* [97严] 严蔚敏，吴伟民，《数据结构C语言版》，清华大学出版社，1997年4月
* [99殷] 殷人昆，陶永雷，谢若阳，盛绪华，《数据结构（用面向对象方法与C++描述）》，清华大学出版社，1999年7月


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
排序算法 |
| --- |
|  |
| 理论 | 
* 計算複雜性理論
* 大O符号
* 全序关系
* 数据结构术语列表
* 原地算法
* 稳定性
* 比较排序
* 自适应排序（英语：）
* 排序网络（英语：）
* 整数排序（英语：）
* X+Y排序（英语：）
* 量子排序（英语：）

 |
|  |
| 交换排序 | 
* 冒泡排序
* 鸡尾酒排序
* 奇偶排序
* 梳排序
* 侏儒排序
* 快速排序
* 慢速排序
* 臭皮匠排序
* Bogo排序

 |
|  |
| 选择排序 | 
* 选择排序
* 堆排序
* 平滑排序（英语：）
* 笛卡尔树排序（英语：）
* 锦标赛排序（英语：）
* 圈排序（英语：）
* 弱堆排序（英语：）

 |
|  |
| 插入排序 | 
* 插入排序
* 希尔排序
* 伸展排序
* 二叉查找树排序
* 图书馆排序
* 耐心排序

 |
|  |
| 归并排序 | 
* 归并排序
* 梯级归并排序（英语：）
* 振荡归并排序（英语：）
* 多相归并排序（英语：）

 |
|  |
| 分布排序 | 
* 美国旗帜排序（英语：）
* 珠排序
* 桶排序
* 爆炸排序（英语：）
* 计数排序
* 比較計數排序
* 插值排序
* 鸽巢排序
* 相邻图排序（英语：）
* 基数排序
* 闪电排序（英语：）

 |
|  |
| 并发排序 | 
* 双调排序器（英语：）
* Batcher归并网络
* 两两排序网络（英语：）

 |
|  |
| 混合排序 | 
* 塊排序（英语：）
* Tim排序
* 内省排序
* Spread排序（英语：）
* 归并插入排序（英语：）

 |
|  |
| 其他 | 
* 拓撲排序
* 煎餅排序
* 意粉排序（英语：）

 |

 |

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
算法 |
| --- |
|  |
| 排序 | 

|  |  |
| --- | --- |
| 比较排序 | 
* 冒泡排序
* 选择排序
* 插入排序
* 希尔排序
* 快速排序
* 归并排序
* 堆排序
* 鸡尾酒排序
* 梳排序
* 侏儒排序
* 图书馆排序
* 内省排序
* 奇偶排序

 |
|  |
| 线性时间排序 | 
* 鸽巢排序
* 基数排序
* 計數排序
* 桶排序

 |
|  |
| 并行排序 | 
* 排序网络（英语：）
* Batcher归并网络

 |
|  |
| 不实用的 | 
* Bogo排序
* 臭皮匠排序

 |
|  |
| 图 | 
* 拓撲排序

 |

 |
|  |
| 搜索 | 

|  |  |
| --- | --- |
| 列表 | 
* 线性搜索
* 二分搜索
* 插值搜尋

 |
|  |
| 树・图 | 
* 广度优先搜索
	+ 最良優先搜索（英语：）
	+ 均一开销搜索
	+ A\*
* 深度优先搜索
	+ 迭代深化深度优先搜索
	+ 深度限制搜索（日语：）
	+ 双向搜索
* 分枝限定法（英语：）

 |
|  |
| 字符串 | 
* KMP算法
* 博耶-穆尔字符串搜索算法
* AC自动机算法
* 拉宾-卡普算法
* bitap算法

 |

 |
|  |
| 最短路问题 | 
* 戴克斯特拉算法
* 贝尔曼-福特算法
* A\*搜尋演算法
* Floyd-Warshall算法

 |
|  |
| 最小生成树 | 
* 普林姆算法
* 克鲁斯克尔演算法

 |
|  |
| 最大流最小割 | 
* 福特-富尔克森算法
* 埃德蒙兹-卡普算法
* 迪尼茨算法

 |
|  |
| 线性规划 | 
* 单纯形法
* 卡马卡尔算法（英语：）

 |
|  |
| 順序統計量 | 
* 选择算法
* 中位数的中位数（英语：）

 |
|  |
| 種類 | 
* 精确算法
* 近似算法
* 随机化算法

 |
|  |
| 其他 | 
* 分治法
* 动态规划
* 贪心算法

 |
|  |
| **Category:算法** |

 |