原理:
http://wenku.baidu.com/view/4550ed19a300a6c30c229f3b.html |
列出全排列的初始思想:
解决一个算法问题,
我比较习惯于从基本的想法做起,我们先回顾一下我们自己是如何写一组数的全排列的:1,3,5,9
1,3,5,9.(第一个)
首先保持第一个不变,对3,5,9进行全排列。 同样地,我们先保持3不变,对5,9进行全排列。 保持5不变,对9对进行全排列,由于9只有一个,它的排列只有一种9。接下来5不能以5打头了,5,9相互交换,得到
1,3,9,5. 此时5,9的情况都写完了,不能以3打头了,得到
1,5,3,9
1,5,9,3
1,9,3,5
1,9,5,3
这样,我们就得到了1开头的所有排列,这是我们一般的排列数生成的过程。再接着是以3、5、9打头,得到全排列。
我们把上面全排列的方法归纳一下,基本上就是:
任意选一个数(一般从小到大或者从左到右)打头,对后面的n-1个数进行全排列。
聪明的读者应该已经发现,这是一个递归的方法,因为要得到n-1个数的全排列,们又要先去得到n-2个数的全排列,而出口是只有1个数的全排列,因为它只有1种,为它的本身。写成比较规范的流程:
1.开始for循环。
2.改变第一个元素为原始数组的第一个元素(什么都没做)。
3.求第2个元素到第n个元素的全排列。
4.要求第2个元素到第n个元素的全排列,要递归的求第3个元素到第n个元素的全排列。
......
5.直到递归到第n个元素到第n元素的全排列,递归出口。
6.将改变的数组变回。
7.改变第一个元素为原始数组的第二个元素。
5.求第2个元素到第n个元素的全排列。
6.要求第2个元素到第n个元素的全排列,要递归的求第3个元素到第n
个元素的全排列。
5.直到递归到第n个元素到第n元素的全排列,递归出口。
6.将改变的数组变回。 ......
8.不断地改变第一个元素,直至n次使for循环中止。
Option Explicit
Const A = 4 '原始数据长度
Const L = 4 '定义全排列的个数
Const H = 720 '输出深度 L!=6*5*4*3*2*1
Public Output(1 To H, 1 To A), nOut&, mOut&
'TeD.Zheng 2014-4-10
'用于解决不重复字符(字母+数字)的全排序
'参考信息:
'http://wenku.baidu.com/view/4550ed19a300a6c30c229f3b.html
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub Permutation()
Dim arr(), i& '原始数据数组,变量
Dim m&, n& '数据交换的变量
'------------------------------------------------
With Sheet1
ReDim arr(1 To A)
For i = 1 To A
arr(i) = .Cells(1, i) '原始数据读入数组
Next
i = 0 '初始化变量
nOut = 0 '初始化变量
mOut = 0
m = 1 '初始化赋值
n = UBound(arr) '初始化赋值
main arr(), m, n
.[A3].Resize(UBound(Output()), L) = Output()
End With
Erase arr()
End Sub
'====================================================
'主程序
Sub Permute(arr(), m, n)
Dim temp '临时数据
Dim i&
If m = n Then
'----------------------------------
'输出数据读入
nOut = nOut + 1
For mOut = 1 To UBound(arr())
Output(nOut, mOut) = arr(mOut)
Next
'----------------------------------
Exit Sub '递归出口
Else
For i = m To n Step 1
temp = arr(m) '交换位置
arr(m) = arr(i)
arr(i) = temp
Permute arr(), m + 1, n
temp = arr(m) '换回位置
arr(m) = arr(i)
arr(i) = temp
Next i
End If
End Sub