排列

排列（）又称置换，是将相异物件或符号根据确定的顺序重排，得到的每个顺序都称作一个-{zh-cn:排列; zh-hk:排列; zh-tw:排列或置换;}-。例如，从1到6的数字有720种排列，对应于由这些数字组成的所有不重复亦不阙漏的序列，例如“4, 5, 6, 1, 2, 3”与“1, 3, 5, 2, 4, 6”。
排列的广义概念在不同语境下有不同的形式定义：
定义.
一个集合的置换为从该集合映至自身的双射函数：
formula_1
恒等置换的定义为置换formula_2使得对所有formula_3，formula_4。
所有关于formula_5个元素的集合formula_6的置换组成的集合构成对称群formula_7，其群运算为函数的复合。因此两个置换，formula_2和formula_9的积formula_10的定义为formula_11。
两个置换的复合一般不满足交换律：formula_12。
置换数的计算.
此节使用置换的传统定义。从formula_5个相异元素中取出formula_14个元素，formula_14个元素的排列数量为：
以赛马为例，有8匹马参加比赛，玩家需要在彩票上填入前三胜出的马匹的号码，从8匹马中取出3匹马来排前3名，排列数量为：
因为一共存在336种可能性，因此玩家在一次填入中中奖的概率应该是：
不过，中国大陆的教科书则是把从n取k的情况记作formula_19或formula_20（A代表Arrangement，即排列）。
重复置换.
上面的例子是建立在取出元素不重复出现状况。
从formula_5个元素中取出formula_14个元素，formula_14个元素可以重复出现，这排列数量为：
以四星彩为例，10个数字取4个数字，因可能重复所以排列数量为：
这时的一次性添入中奖的概率就应该是：
抽象代数.
在集合论与抽象代数等领域中，「置-{}-换」一词被保留为集合（通常是有限集）到自身的双射的一个称呼。例如对于从一到十的数字构成的集合，其置-{}-换将是从集合 formula_27 到自身的双射。因此，置-{}-换是拥有相同定义域与上域的函数，且其为双射的。一个集合上的置-{}-换在函数合成运算下构成一个群，称为对称群或置换群。
符号.
以下仅考虑有限集上的置-{}-换（视为双射），由于 formula_5 个元素的有限集可以一一对应到集合 formula_29，有限集的置-{}-换可以化约到形如 formula_29 的集合之置-{}-换。此时有两种表示法。
第一，利用矩阵符号将"自然"排序写在第一列，而将置-{}-换后的排序写在第二列。例如：
表示集合 {1,2,3,4,5} 上的置-{}-换 formula_32。
第二，借由置-{}-换的相继作用描述，这被称为「轮换分解」。分解方式如下：固定置-{}-换 formula_33。对任一元素 formula_34，由于集合有限而 formula_33 是双射，必存在正整数 formula_36 使得 formula_37，故可将置-{}-换 formula_33 对 formula_34 的相继作用表成 formula_40，其中 formula_41 是满足 formula_42 的最小正整数。
称上述表法为 formula_34 在 formula_33 下的轮换， formula_41 称为轮换的长度。此处将轮换视作环状排列，例如
是同一个轮换。由此可知 formula_34 在 formula_33 下的轮换只决定于 formula_34 在 formula_33 作用下的轨道，于是，任两个元素 formula_52 或给出同一个轮换，或给出不交的轮换。
将轮换 formula_53 理解为一类特殊的置-{}-换，即可递置-{}-换：仅须定义置-{}-换 formula_33 为 formula_55，而在其它元素上定义为恒等映射。不交的轮换在函数合成的意义下可相交换。
因此，可以将集合 {1, ..., n} 对一置-{}-换分解成不交轮换的合成，此分解若不计顺序则是唯一的。例如前一个例子的 formula_33 就对应到 (1 2 5) (3 4) 或 (3 4) (1 2 5)。
轮换.
轮换一是种特殊的置换。
如果给定formula_57是formula_58上的一个置换，formula_59为formula_58上的一个子集。
若有
formula_61
formula_62
则称formula_63 为一个轮换。formula_64 为轮换的长度。
特殊置换.
在上节的置换表法中，长度等于二的环状置换称为换位，这种环状置换 formula_65 不外是将元素 formula_52 交换，并保持其它元素不变。对称群可以由换位生成。
由于环状置换长度为formula_64的置换formula_68可分解为最少formula_69个换位，若formula_14为偶数，则formula_68为偶换位，否则formula_68为奇换位。即环状置换的长度为奇数，该置换为偶换位；环状置换的长度为偶数，该置换为奇换位。
由此可定义任一置换的奇偶性，并可证明：一个置换是偶换位的充要条件是它可以由偶数个换位生成。偶换位在置换群中构成一个正规子群，称为交错群。
计算理论中的置换.
某些旧课本将置换视为变数值的赋值。在计算机科学中，这就是将值1, 2, ..., formula_5赋予变数formula_74, formula_75, ..., formula_76的赋值运算子，并要求每个值只能赋予一个变数。
赋值/代入的差别表明函数式编程与指令式编程之差异。纯粹的函数式编程并不提供赋值机制。现今数学的惯例是将置换看作函数，其间运算看作函数合成，函数式编程也类似。就赋值语言的观点，一个代入是将给定的值「同时」重排，这是个有名的问题。
置换图.
取一个无向图formula_77，将图formula_77的formula_5个顶点标记为formula_80, ..., formula_81，对应一个置换（formula_82），若且唯若formula_83而formula_84，则图的formula_85和formula_86相连，这样的图称为置换图。
置换图的补图必是置换图。
使用计算器.
多数计算器都有个计算置换数的 "nPr" 键。然而此键在一些最先进的桌上型机种中却被隐藏了。例如：在 TI-83 中，按 MATH、三次右键、再按二。在卡西欧的图形计算机中，按 OPTN，一次右键（F6）、PROB（F3）、nPr（F2）。
试算表语法.
多数试算表软件都有函式 PERMUT("Number"，"Number chosen")，用以计算置换。"Number" 是描述物件数量的一个整数，"Number chosen" 是描述每个置换中所取物件数的整数。
C++演算范例.
回圈法.
using namespace std;
bool arrsame(int* arr, int len, int num) {
 int i;
 for (i = 0; i &lt; 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] &gt;= n &amp;&amp; i--));
 if (perm[0] &gt;= n)
 return 0;
 for (int num = 0, seat = i + 1; seat &lt; 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 &lt; k || k &lt;= 0)
 return 0;
 int* perm = new int[k];
 for (int i = 0; i &lt; k; i++)
 perm[i] = i;
 do
 for (int i = 0; i &lt; k; cout « ((++i &lt; k) ? ',' : '\n'))
 cout « perm[i] + 1;
 while (next_perm(perm, k, n));
 delete[] perm;
 return 0;
递回法.
using namespace std;
struct prem {
 int len;
 vector&lt;int&gt; used, position;
 function&lt;void(vector&lt;int&gt;&amp;)&gt; action;
 void run(int now = -1) {
 if (now == len - 1) {
 action(position);
 return;
 int next = now + 1;
 for (int i = 0; i &lt; 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, [&amp;](vector&lt;int&gt;&amp; p) {
 for (int i = 0; i &lt; len; i++) {
 cout « p[i] « " ";
 cout « endl;
 p.run();
 return 0;
python演算范例.
import sys
def perm(dim, num):
 if not 0 &lt;= num &lt;= dim:
 print('It must be that 0 &lt;= num &lt;= 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