在线性代数中,经常要接触到行列式,他是实现很多线性代数运算的基础工具。求行列式就需求全一个数列的全排列,全排列的数学定义为:
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。公式:全排列数f(n)=n!(定义0!=1)
其实在Python中,已经能通过Python自带的库itertools.permutations 来实现,参考文档为
https://docs.python.org/2/library/itertools.html#itertools.permutations
下面我们通过自行编写代码的方式,在Python中实现全排列的算法,最容易想到的就是递归的方式;并且可以通过两种途径来实现它,一种是大家常见的list序列方式,一种是使用yield 迭代方式
一、序列实现方式
def perm1(iter,iterlist=[],iterlist_total=[]):
"""
全排列函数
:param iter:需要全排列的序列
:param iterlist: 在递归中传递已经被排列的序列,初始不需要赋值
:param iterlist_total: 在递归中传递已经被全部被成功完成排列的序列,初始不需要赋值
:return:返回全排列的个数
原理是使用递归
ex:
例如:
[1, 2, 3, 4, 5, 6]
先将1,取出来身剩下的元素组成的序列再次排列
然后在将2取出来,剩下的元素组成的序列(注意必须包含1,这点注意,不然元素个数越来越减少)再次排列
当递归到iter只有一个的时候,递归停止
"""
if len(iter)<=1:
iterlist=iterlist+iter
iterlist_total.append(iterlist)
else:
for i,j in enumerate(iter):
"""这种写法是典型的在list中,去掉当前索引为i的元素,得到其余的元素组成的列表的写法
可以用list(set(iter)-set([j]))这种写法,但是转换的过程中,会将iter重新排序,在
一些程序中不适用"""
perm1(iter[:i]+iter[i+1:],iterlist+[j],iterlist_total)
return iterlist_total
二、yield 迭代实现方式
def perm2(iter):
"""
全排列函数,通过yield实现
:param iter:需要全排列的序列
:param iter:
:return:
注意:程序中有两个yield出口
"""
if len(iter)<=1:
yield iter
else:
for i, j in enumerate(iter):
"""这种写法是典型的在list中,去掉当前索引为i的元素,得到其余的元素组成的列表的写法
可以用list(set(iter)-set([j]))这种写法,但是转换的过程中,会将iter重新排序,在
一些程序中不适用"""
for e in perm2(iter[:i] + iter[i + 1:]):
"""相当于,将剩下的元素进行全排列,因perm2是返回的是迭代对象,只能通过for将其一个一个的取出
来,然后和 上一个 for 循环的 j 组成全排列"""
yield [j]+e
验证一下
def main():
i=perm1([1,2,3])
for item in i:
print(item)
print("permutations count:{}".format(len(i)))
i=perm2([1,2,3])
for item in i:
print(item)
实现的结果如下:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
permutations count:6
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
资料参考:
How to generate all permutations of a list in Python
在stackoverflow上面介绍了N种实现方式
https://stackoverflow.com/questions/104420/how-to-generate-all-permutations-of-a-list-in-python#
python使用递归解决全排列数字示例
https://www.jb51.net/article/46631.htm