**耐心排序**（Patience Sort）是將陣列的元素分類成很多堆再串接回陣列的一種排序演算法。

操作解說
----

* 建立一個堆陣列
* 比較目前指向的元素和每個堆的第一個元素，計算出比目前元素小的堆數量
* 若目前元素比所有堆的第一個元素大，建立新的堆並加入到堆陣列中，否則將目前元素加入到第「比目前元素小的堆數量」個堆
* 分類完後將每個堆反序然後對每個堆再做耐心排序
* 最後將每個堆串接並儲存回原本的陣列

演示操作一次耐心排序分堆過程
--------------

假設目前欲排序的數列為: 3, 5, 7, 1, 4

*Step 1*:
取出數字 3, 由於目前沒有任何堆所以產生**一號堆**並把 3 放入

* 堆 一
	+ 內容: 3

  

*Step 2*:
取出數字 5, 5 比一號堆的第一個數字 3 大, 故產生**二號堆**並把 5 放入

* 堆 一
	+ 內容: 3
* 堆 二
	+ 內容: 5

  

*Step 3*:
取出數字 7, 7 比一號堆和二號堆的第一個數字大, 故產生**三號堆**並把 7 放入

* 堆 一
	+ 內容: 3
* 堆 二
	+ 內容: 5
* 堆 三
	+ 內容: 7

  

*Step 4*:
取出數字 1, 所有堆的第一個數字都比 1 大, 故放入**一號堆**

* 堆 一
	+ 內容: 3, 1
* 堆 二
	+ 內容: 5
* 堆 三
	+ 內容: 7

  

*Step 5*:
取出數字 4, 只有一號堆的第一個數字比 4 小, 所以將 4 放入**二號堆**

* 堆 一
	+ 內容: 3, 1
* 堆 二
	+ 內容: 5, 4
* 堆 三
	+ 內容: 7

實作範例
----

### C++11

```
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

template<typename T>
vector<T>& operator<<(vector<T>& vi, vector<T>& vx) { //串接陣列
 int len = vi.size();
 vi.resize(vi.size() + vx.size());
 for (int i = 0; i < (int) vx.size(); i++)
 vi[i + len] = vx[i];
 return vi;
}
template<typename T>
void reverse(vector<T>& arr) { //陣列反序
 int len = arr.size();
 for (int i = 0; i < len - 1 - i; i++)
 swap(arr[i], arr[len - 1 - i]);
}

template<typename T>
void patience\_sort(vector<T>& arr) {
 int len = arr.size();
 if (len < 2)
 return;
 vector<vector<T> > piles;
 for (int i = 0; i < len; i++) { //將陣列元素分堆
 vector<T> new\_pile = { arr[i] };
 int insert;
 for (insert = 0; insert < (int) piles.size(); insert++) //計算目前元素比多少個堆陣列第一個元素還大
 if (new\_pile[0] < piles[insert][0])
 break;
 if (insert == (int) piles.size())
 piles.push\_back(new\_pile);
 else
 piles[insert].push\_back(arr[i]);
 }
 arr.clear();
 for (int j = 0; j < (int) piles.size(); j++) {
 reverse(piles[j]); //因為排出來的堆陣列第一個元素是該陣列最大值，故要反序
 patience\_sort(piles[j]);
 arr << piles[j]; //串接陣列
 }
}

template<typename T>
ostream& operator<<(ostream& os, vector<T> v) { //顯示陣列內容
 int len = v.size();
 for (int i = 0; i < len; cout << (++i == len ? "" : ","))
 os << v[i];
 return os;
}

int main() {
 vector<int> arr = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
 cout << arr << endl;
 patience\_sort(arr);
 cout << arr << endl;
 return 0;
}

```

### Python 3.10

```
def to\_piles(arr: list) -> list:
    if len(arr) == 1:
        return arr

    piles: list = []
    for a in arr:
        if not piles:
            piles.append([a])
            continue

        for pile in piles:
            if pile[0] > a:
                pile.append(a)
                break
        else:
            piles.append([a])

    return piles

def patience\_sort(arr: list):
    piles: list = to\_piles(arr)
    is\_sorted: bool = True
    while is\_sorted:
        temp\_piles: list = []
        is\_sorted = False

        for pile in piles:
            if len(pile) == 1:
                temp\_piles.append(pile)
                continue

            is\_sorted = True
            pile.reverse()
            temp\_piles += to\_piles(pile)

        piles.clear()
        piles += temp\_piles

    arr.clear()
    arr += [pile[0] for pile in piles]

if \_\_name\_\_ == '\_\_main\_\_':
    arr = [3, 7, 5, 1, 3, 6, 4, 0, 8, 2]
    patience\_sort(arr)
    print(arr)

```

其他連結
----

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

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

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

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

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

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

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

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

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

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

 |

 |