在數學分支裡,排列與組合是不分家的。於是,動手寫下本文。在上一文中,采用了遞歸調用,雖然便於理解,但是算法的效率上打個折扣。本文一並重寫,改為循環調用。
代碼賦予其後,用的是VB2005
兩個類,一個是clsPermutation,用來計算排列的;一個是clsCombination,用來計算組合的。下面,把各個函數說明一下。
類clsPermutation:
函數:GetPermutation
獲得指定標號的排列,返回值是一個數組
參數: Lower,排列中的下限
Upper,排列中的上限
Count,排列中的元素的個數
Index,該排列的標號
示例: tI=GetPermutation(1,8,4,23)
返回一個從1到8中選4個數的一個排列,標號為23
函數:GetPermutationRandom
獲得隨機的排列,返回值是一個數組
參數: Lower,排列中的下限
Upper,排列中的上限
Count,排列中的元素的個數
示例: tI=GetPermutation(1,8,4)
返回一個從1到8中選4個數的一個排列
函數:Factorial
獲得指定參數的階乘,返回值是一個整數
參數: N,指定參數
示例: tI=Fratorial(4)
返回4的階乘,為24
函數:P
獲得指定參數的排列數,返回值是一個整數
參數: M,指定參數上標;N,指定參數下標
示例: tI=P(2,6)
計算P(2,6)的值,為30
類clsCombination:
函數:GetCombination
獲得指定標號的排列,返回值是一個數組
參數: Lower,排列中的下限
Upper,排列中的上限
Count,排列中的元素的個數
Index,該排列的標號
示例: tI=GetCombination(1,8,4,23)
返回一個從1到8中選4個數的一個組合,標號為23
函數:GetCombinationRandom
獲得隨機的排列,返回值是一個數組
參數: Lower,排列中的下限
Upper,排列中的上限
Count,排列中的元素的個數
示例: tI=GetCombination(1,8,4)
返回一個從1到8中選4個數的一個組合
函數:C
獲得指定參數的排列數,返回值是一個整數
參數: M,指定參數上標;N,指定參數下標
示例: tI=C(2,6)
計算C(2,6)的值,為15
代碼格式修正於2012年1月5日
Public Class clsPermutation
Private Shared mList() As Integer
Public Shared Function GetPermutationRandom(ByVal Lower As Integer, ByVal Upper As Integer, ByVal Count As Integer) As Integer()
If Count > Upper - Lower + 1 Then Return Nothing
If Count <= 0 Then Return Nothing
If Lower > Upper Then Return Nothing
If Lower < 0 OrElse Upper < 0 Then Return Nothing
Dim i As Integer
ReDim mList(Upper - Lower)
For i = 0 To mList.GetUpperBound(0)
mList(i) = Lower + i
Next
Dim tR As New Random
Call GetP(Upper - Lower + 1, Count, tR.Next(P(Count, Upper - Lower + 1)), 0)
ReDim Preserve mList(Count - 1)
Return mList
End Function
Public Shared Function GetPermutation(ByVal Lower As Integer, ByVal Upper As Integer, ByVal Count As Integer, ByVal Index As Integer) As Integer()
If Count > Upper - Lower + 1 Then Return Nothing
If Count <= 0 Then Return Nothing
If Lower > Upper Then Return Nothing
If Lower < 0 OrElse Upper < 0 Then Return Nothing
ReDim mList(Upper - Lower)
Dim i As Integer
For i = 0 To mList.GetUpperBound(0)
mList(i) = Lower + i
Next
Call GetP(Upper - Lower + 1, Count, Index, 0)
ReDim Preserve mList(Count - 1)
Return mList
End Function
Private Shared Sub GetP(ByVal Range As Integer, ByVal Count As Integer, ByVal Index As Integer, ByVal Start As Integer)
Dim i As Integer, j As Integer
Do While Count > 0
j = P(Count, Range)
Index = Index Mod j
i = Int(Index / (j / Range))
Call clsData.SwapNumber(mList(Start), mList(Start + i))
Range -= 1
Count -= 1
Start += 1
Loop
End Sub
Public Shared Function Factorial(ByVal N As Integer) As Integer
Dim i As Integer, S1 As Integer = 1
If N < 0 Then Return 0
For i = 1 To N
S1 *= i
Next
Return S1
End Function
Public Shared Function P(ByVal M As Integer, ByVal N As Integer) As Integer
Dim i As Integer, S1 As Integer = 1