针对一个数组/列表进行全排列有两种方法,一种是切片的方法,一种是调换顺序
切片
切片的方法实际上和高中数学讲的是一样的,有一个n维列表/数组,第一个位置有n种选择,第二个有n-1中选择(不包括前一个第一个选中的数),依次类推。。。
def perm(data):
if len(data) == 1:#和阶乘一样,需要有个结束条件
return [data]
r = []
for i in range(len(data)):
s = data[:i] + data[i+1:] #去掉第i个元素,进行下一次的递归
p = perm(s)
for x in p:
r.append(data[i:i+1]+x) #一直进行累加
return r
data = [1,2,3]
print(perm(data))
这种方法便于理解
调换顺序
这种实际上遍历列表/数组中所有可能的顺序,并进行赋值
def perm(lis,begin,end): #调换顺序
#print "调用perm函数"
if begin>=end: #等到所有循环走完,直接进行输出
print(lis)
else:
i = begin
for num in range(begin,end):
lis[num],lis[i] = lis[i],lis[num] #固定当前位置,在进行下一位的排列
perm(lis,begin+1,end) #在这一步就可以输出结果
# 调用结束之后还需要回溯将交换位置的元素还原,以供其他下降路径使用(二叉树)
lis[num],lis[i] = lis[i],lis[num]
输出
global stackB
stackB = [None] * 全排列个数
global top
top = -1
def push(data):
global top #如果没有这些,相当于其为局部变量
# global stackB
if top >= 全排列个数:
print('堆栈已满,无法再加入')
else:
top += 1
stackB[top] = data
print('压栈数据:',data)
def perm(lis,begin,end): #调换顺序
if begin >= end:
push(copy.copy(lis))
print(lis)
else:
i = begin
for num in range(begin,end):
lis[num],lis[i] = lis[i],lis[num] #固定当前位置,在进行下一位的排列
perm(lis,begin+1,end)
# 调用结束之后还需要回溯将交换位置的元素还原,以供其他下降路径使用(二叉树)
lis[num],lis[i] = lis[i],lis[num]
stackA = list(range(1,n+1)) # 输入数据
perm(stackA,0,len(stackA))
print(stackB)