**图书馆排序**，或**空位插入排序**是一种排序算法 ，它基于插入排序，但在每两个元素之间存在空位，以便于加速随后的插入。这个名字来自一个比喻：

> 假设一名图书管理员在一个长架上按字母顺序來整理书，从左边A開頭的書，一直到右边Z開頭的書，书本之间没有空格。如果图书管理员有一本開頭為B的新书，当他找到了這本書在B區中的正确位置，他将不得不把從該位置後一直到Z的每一本书向右移动，就只是为了腾出空位放置这本新书。这就是插入排序的原理。但是，如果他在每一字母區後留有額外的空間，只要在B區之后還有空间，他插入书時就只需要移动少数几本书，而不会移动后面所有的书，这是图书馆排序的原理。
> 
> 

此算法由 Michael A. Bender、Martín Farach-Colton和Miguel Mosteiro 于2004年提出，并于2006年出版。

图书馆排序像插入排序一样，是稳定的排序算法，并且它是在线排序；然而，它被证明在大部分情况下具有O(n log n)的运行速度（相当于快速排序），而不是插入排序的O(n2)。用于此改进的机制与跳过列表非常相似。本文没有给出完整的实现，也没有重要部分的确切算法，如插入和重新平衡。需要更多的信息来比较图书馆排序的效率与现实中其他排序方法的效率。

相比基本的插入排序，图书馆排序的缺点是需要额外空间。该空间的大小将取决于实作的情況。在本文中，需要的空间为*(1+ε)n*,，但没有进一步的建议如何选择ε。

插入排序的一个缺点是它可能需要大量的交换操作，并且如果内存写入是昂贵的，则成本很高。图书馆排序可能会在插入步骤中有所改进，因为騰出空間所需移动的次數較少，但也因此在重新平衡步骤中增加了额外的成本。另外，由于随机数据集中的每个插入都可以访问不再处于高速缓存中的内存，特别是对于大型数据集，因此与归并排序相比，引用的局部性将变差。

实现
--

### 算法

现在我们有大小为n个元素的数组。我们选择每两个元素之间的空位，那么我们将有一个最大的数组（1 +ε）n。该算法在log n轮中工作。我们通过二分查找来找到插入的位置，然后交换后面的元素，直到我们命中一个空格。一旦结束，我们通过在每个元素之间插入空格来重新平衡最终的数组。

算法根据以下三个重要的步骤：

1. 二分查找：我们在已经插入的元素中，二分查找这个元素应该插入的位置。这可以通过线性移动到阵列的左侧或右侧，如果您点击中间元素中的空格。

2. 插入:
将元素插入到正确的位置，并且通过交换把后面的元素向右移动，直到空格。

3. 重新平衡：在数组中的每对元素之间插入空格。这需要线性时间，并且由于算法只运行log n轮，总重新平衡只需要O（n log n）时间。

### 伪代码

```
**proc** rebalance(A, begin, end)
    r ← end
    w ← end * 2
    **while** r >= begin
        A[w+1] ← gap
        A[w] ← A[r]
        r ← r - 1
        w ← w - 2
```

```
**proc** sort(A)
    n ← length(A)
    S ← new array of n gaps
    **for** i ← 1 to floor(log2(n) + 1)
        **for** j ← 2^i to 2^(i+1)
            ins ← binarysearch(A[j], S, 2^(i-1))
            insert A[j] at S[ins]
```

在这里，`binarysearch(A，k)`是执行二分查找中的*A*中的第k个元素，并且跳过空格，找到元素A[j]应该插入的位置。插入应该优于填补元素的空格。

参考资料
----

1. ↑ .  [2017-03-28]. （原始内容存档于2016-08-25）.
2. ↑  Bender, M. A.; Farach-Colton, M.; Mosteiro M.. Theory of Computing Systems. 2006, **39** (3): 391. doi:10.1007/s00224-005-1237-z.

外部链接
----

* Gapped Insertion Sort（页面存档备份，存于）


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

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

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

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

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

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

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

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

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

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

 |

 |

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

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

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

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

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

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

 |
|  |
| 图 | 
* 拓撲排序

 |

 |
|  |
| 搜索 | 

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

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

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

 |

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

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

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

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

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

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

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

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

 |