P(3,3)=6
**排列**（英語：）是將相異物件或符號根據確定的順序重排。每個順序都稱作一個。例如，從一到六的數字有720種排列，對應於由這些數字組成的所有不重複亦不闕漏的序列，例如"4, 5, 6, 1, 2, 3" 與*1, 3, 5, 2, 4, 6*。

置換（排列）的廣義概念在不同語境下有不同的形式定義：

* 在集合論中，一個集合的置換是從該集合映至自身的雙射；在有限集的情況，便與上述定義一致。
* 在組合數學中，置換一詞的傳統意義是一個有序序列，其中元素不重複，但可能有闕漏。例如*1,2,4,3*可以稱為*1,2,3,4,5,6*的一個置換，但是其中不含*5,6*。此時通常會標明為「從n個對象取r個對象的置換」。

置換數的计算
------

此節使用置換的傳統定義。从{\displaystyle n}个相異元素中取出{\displaystyle k}个元素，{\displaystyle k}个元素的排列數量為：

{\displaystyle P\_{k}^{n}={\frac {n!}{(n-k)!}}}
其中**P**意为Permutation（排列），**!**表示階乘運算。

以賽馬為例，有8匹马参加比赛，玩家需要在彩票上填入前三胜出的马匹的号码，從8匹馬中取出3匹馬來排前3名，排列數量為：

{\displaystyle P\_{3}^{8}={\frac {8!}{(8-3)!}}=336}
因为一共存在336种可能性，因此玩家在一次填入中中奖的概率应该是：

{\displaystyle P={\frac {1}{336}}=0.00298}
不過，中國大陸的教科書則是把從n取k的情況記作{\displaystyle P\_{n}^{k}}或{\displaystyle A\_{n}^{k}}（A代表Arrangement，即排列）。

重複置換
----

上面的例子是建立在取出元素不重複出現狀況。

從{\displaystyle n}个元素中取出{\displaystyle k}个元素，{\displaystyle k}个元素可以重复出现，這排列數量為：

{\displaystyle U\_{k}^{n}=n^{k}}
以四星彩為例，10個數字取4個數字，因可能重複所以排列數量為：

{\displaystyle U\_{4}^{10}=10^{4}=10000}
这时的一次性添入中奖的概率就应该是：

{\displaystyle P={\frac {1}{10000}}=0.0001}

抽象代數
----

在集合論與抽象代數等領域中，「置換」一詞被保留為集合（通常是有限集）到自身的雙射的一個稱呼。例如對於從一到十的數字構成的集合，其置換將是從集合 {\displaystyle \{1,\ldots ,10\}} 到自身的雙射。因此，置換是擁有相同定義域與上域的函數，且其為雙射的。一個集合上的置換在函數合成運算下構成一個群，稱為對稱群或置換群。

符號
--

更多：對稱群 (n次对称群)
以下僅考慮有限集上的置換（視為雙射），由於 {\displaystyle n} 個元素的有限集可以一一對應到集合 {\displaystyle \{1,\ldots ,n\}}，有限集的置換可以化約到形如 {1, ... n} 的集合之置換。此時有兩種表示法。

第一，利用矩陣符號將*自然*排序寫在第一列，而將置換後的排序寫在第二列。例如：

{\displaystyle {\begin{bmatrix}1&2&3&4&5\\2&5&4&3&1\end{bmatrix}}}
表示集合 {1,2,3,4,5} 上的置換 {\displaystyle s:s(1)=2,s(2)=5,s(3)=4,s(4)=3,s(5)=1}。

第二，藉由置換的相繼作用描述，這被稱為「轮换分解」。分解方式如下：固定置換 {\displaystyle s}。對任一元素 {\displaystyle x}，由於集合有限而 {\displaystyle s} 是雙射，必存在正整數 {\displaystyle N} 使得 {\displaystyle s^{N}(x)=x}，故可將置換 {\displaystyle s} 對 {\displaystyle x} 的相繼作用表成 {\displaystyle (x\;s(x)\;s^{2}(x)\cdots s^{m-1}(x))}，其中 {\displaystyle m} 是滿足 {\displaystyle s^{m}(x)=x} 的最小正整數。

稱上述表法為 {\displaystyle x} 在 {\displaystyle s} 下的**轮换**， {\displaystyle m} 稱為轮换的**長度**。我們在此將轮换視作環狀排列，例如

{\displaystyle (a\_{1}\;a\_{2}\;a\_{3}\cdots a\_{m})} 與
{\displaystyle (a\_{m}\;a\_{1}\;a\_{2}\cdots a\_{m-1})}
是同一個轮换。由此可知 {\displaystyle x} 在 {\displaystyle s} 下的**轮换**只決定於 {\displaystyle x} 在 {\displaystyle s} 作用下的軌道，於是，任兩個元素 {\displaystyle x,y} 或給出同一個轮换，或給出不交的轮换。

我們將轮换 {\displaystyle (x\_{1}\;\cdots x\_{m})} 理解為一類特殊的置換：僅須定義置換 {\displaystyle s} 為 {\displaystyle s:x\_{1}\mapsto x\_{2},\ldots ,x\_{m-1}\mapsto x\_{m},x\_{m}\mapsto x\_{1}}，而在其它元素上定義為恆等映射。不交的轮换在函數合成的意義下可相交換。

因此我們可以將集合 {1, ... n} 對一置換分解成不交轮换的合成，此分解若不計順序則是唯一的。例如前一個例子的 {\displaystyle s} 就對應到 (1 2 5) (3 4) 或 (3 4) (1 2 5)。

輪換
--

輪換一是種特殊的置換。

如果給定{\displaystyle f:X\rightarrow X}是{\displaystyle X}上的一個置換，{\displaystyle A}為{\displaystyle X}上的一個子集。

若有

{\displaystyle \exists A\subset X,A=\{x\_{1},x\_{2},\cdots ,x\_{l}\}}

{\displaystyle {\begin{cases}f(x\_{1})=x\_{2},f(x\_{2})=x\_{3},\cdots ,f(x\_{l})=x\_{1}\\f(x)=x,x\not \in A\end{cases}}}

則稱{\displaystyle f} 為一個輪換。{\displaystyle l} 為輪換的長度。

特殊置換
----

在上節的置换表法中，長度等於二的環狀置换稱為**換位**，這種環狀置换 {\displaystyle (x\;y)} 不外是將元素 {\displaystyle x,y} 交換，並保持其它元素不變。對稱群可以由換位生成。

由於環狀置換長度為{\displaystyle l}的置換{\displaystyle C}可分解為最少{\displaystyle k=l-1}個換位，若{\displaystyle k}為偶數，則{\displaystyle C}為**偶換位**，否則{\displaystyle C}為**奇換位**。即環狀置換的長度為奇數，該置換為**偶換位**；環狀置換的長度為偶數，該置換為**奇換位**。

由此可定義任一置換的奇偶性，並可證明：一個置換是偶換位的充要條件是它可以由偶數個換位生成。偶换位在置換群中構成一個正規子群，稱為交错群。

計算理論中的置換
--------

某些舊課本將置換視為變數值的*賦值*。在計算機科學中，這就是將值

1, 2, ... *n*
賦予變數

*x*1, *x*2, ... *x**n*
的賦值運算子，並要求每個值只能賦予一個變數。

賦值/代入的差別表明函數式編程與指令式編程之差異。純粹的函數式編程並不提供賦值機制。現今數學的慣例是將置換看作函數，其間運算看作函數合成，函數式編程也類似。就賦值語言的觀點，一個代入是將給定的值「同時」重排，這是個有名的問題。

置換圖
---

(2,5,1,4,3,6)的置換圖
取一個無向圖*G*，將圖*G*的*n*個頂點標記*v*1,...*v*n，對應一個置換( s(1) s(2) ... s(*n*) )，若且唯若s(*i*) < s(*j*) 而 *i* > *j*，則圖的*v*i和*v*j相連，這樣的圖稱為置換圖。

置換圖的補圖必是置換圖。

使用計算器
-----

多數計算器都有個計算置換數的 *nPr* 鍵。然而此鍵在一些最先進的桌上型機種中卻被隱藏了。例如：在 TI-83 中，按 MATH、三次右鍵、再按二。在卡西歐的圖形計算機中，按 OPTN，一次右鍵（F6）、PROB（F3）、nPr（F2）。

試算表語法
-----

多數試算表軟件都有函式 PERMUT(*Number*，*Number chosen*)，用以計算置換。*Number* 是描述物件數量的一個整數，*Number chosen* 是描述每個置換中所取物件數的整數。

C++演算範例
-------

### 迴圈法

```
#include <iostream>
using namespace std;
bool arrsame(int\* arr, int len, int num) {
 int i;
 for (i = 0; i < len; i++)
 if (arr[i] == num)
 break;
 return i != len;
}
bool next\_perm(int\* perm, const int k, const int n) {
 int i = k - 1;
 do
 perm[i]++;
 while (arrsame(perm, i, perm[i]) || (perm[i] >= n && i--));
 if (perm[0] >= n)
 return 0;
 for (int num = 0, seat = i + 1; seat < k; num++)
 if (!arrsame(perm, i + 1, num))
 perm[seat++] = num;
 return 1;
}
int main() {
 int n, k;
 cout << "perm(n,k):" << endl;
 cin >> n >> k;
 if (n < k || k <= 0)
 return 0;
 int\* perm = new int[k];
 for (int i = 0; i < k; i++)
 perm[i] = i;
 do
 for (int i = 0; i < k; cout << ((++i < k) ? ',' : '\n'))
 cout << perm[i] + 1;
 while (next\_perm(perm, k, n));
 delete[] perm;
 return 0;
}

```

### 遞迴法

```
#include <bits/stdc++.h>
using namespace std;

struct prem {
 int len;
 vector<int> used, position;
 function<void(vector<int>&)> action;
 prem(int l = 0, function<void(vector<int>&)> a = [](vector<int>& position) {}) : len(l), used(l, -1), position(l), action(a) {}
 void run(int now = -1) {
 if (now == len - 1) {
 action(position);
 return;
 }
 int next = now + 1;
 for (int i = 0; i < len; i++) {
 if (used[i] == -1) {
 used[i] = next;
 position[next] = i;
 run(next);
 used[i] = -1;
 }
 }
 }
};
int main() {
 ios::sync\_with\_stdio(false), cin.tie(0);
 int len = 4;
 prem p(len, [&](vector<int>& p) {
 for (int i = 0; i < len; i++) {
 cout << p[i] << "";
 }
 cout << endl;
 });
 p.run();
 return 0;
}

```

python演算範例
----------

```
import sys

def perm(dim, num):
    if not 0 <= num <= dim:
        print('It must be that 0 <= num <= dim!', flush=True, file=sys.stderr)
        return []

    result = []
    xstack = []

    arr = []
    xset = set(range(dim, 0, -1))

    xstack.append((arr, xset))

    while len(xstack):
        theArr, theSet = xstack.pop()
        for theInt in theSet:
            newSet = theSet.copy()
            newSet.remove(theInt)
            newArr = theArr.copy()
            newArr.append(theInt)
            if num == len(newArr):
                result.append(newArr)
            else:
                xstack.append((newArr, newSet))
    return result

```

參考文獻
----

1. ↑ . 北京市海淀区中关村南大街17号院1号楼: 人民教育出版社. : 17  [2024-03-30]. ISBN 978-7-107-34598-2.
2. ↑ . 九章出版社. : 29.  OCLC:44527392

* Miklos Bona. "Combinatorics of Permutations", Chapman Hall-CRC, 2004. ISBN 978-1-58488-434-7.
* Donald Knuth. *The Art of Computer Programming*, Volume 4: *Generating All Tuples and Permutations*, Fascicle 2, first printing. Addison-Wesley, 2005. ISBN 978-0-201-85393-3.
* Donald Knuth. *The Art of Computer Programming*, Volume 3: *Sorting and Searching*, Second Edition. Addison-Wesley, 1998. ISBN 978-0-201-89685-5. Section 5.1: Combinatorial Properties of Permutations, pp.11–72.

外部連結
----

* 許多排列組合問題，附詳解。 （页面存档备份，存于）（英文）
* 置換及圖論問題  （页面存档备份，存于）（英文）