排列组合的算法 (algorithms for calculating permuration and combination)

 

排列组合的算法

 

定义字典序:

如果两个单词长度不同,较短的单词的每一个字符都和较长的单词相应的字符相同,那么短单词排在长单词的前面。

如果两个单词有相同或不同的长度,某个位置对应的字符不同,则单词的排序由左起第一个不同的字符来决定。

 

Lexicographic order

Let a=s1s2…sp and b=t1t2…tq be strings over {1,2,…n}. We say that a is lexicographically less than b and write a<b if either

(a)    p<q and si=ti for I=1,…,p,

or

(b)    for some I, si<>ti, and for the smallest such I, we have si<ti.

 

这里排列组合的算法都是基于字典序的,按字典序从小到大的顺序列出所有排列或组合,根据字典序发现规律,推导出算法。

 

求组合C(r,n)的算法,n是元素个数,r是选取的元素个数。

Given a string a=s1…sr, which represents r-combination {s1,…,sr}, to find the next string b=t1…tr, we find the rightmost element sm that is not at its maximum value.(sr may have the maximum value n, Sr-1 may have the maximum value n-1, etc). Then

       Ti=si, for I=1, … , m-1.

The element tm is equal to sm+1. For the remainder of the string b we have Tm+1=sm+2, tm+2=sm+3, etc.

如下面的C(4,6)例子:

1 2 3 4

1 2 3 5

1 2 3 6

1 2 4 5

1 2 4 6

1 2 5 6

1 3 4 5

1 3 4 6

1 3 5 6

1 4 5 6

2 3 4 5

2 3 4 6

2 3 5 6

2 4 5 6

3 4 5 6

 

求组合P(n,n)的算法,Pr,n)的算法可以由C(r,n)P(r,r)得到。

已知单词a=s1…sn, 为了得到下一个单词b=t1…tn,从右至左找到一个位置d,它右面的数r>d。然后把d后面的数中最小的大于d的数(从右向左搜索)和d交换,再把d所在位置后面的序列调整为由小到大的顺序。

如下面P(4,4)的例子:

1 2 3 4

1 2 4 3

1 3 2 4

1 3 4 2

1 4 2 3

1 4 3 2

2 1 3 4

2 1 4 3

2 3 1 4

2 3 4 1

2 4 1 3

2 4 3 1

3 1 2 4

3 1 4 2

3 2 1 4

3 2 4 1

3 4 1 2

3 4 2 1

4 1 2 3

4 1 3 2

4 2 1 3

4 2 3 1

4 3 1 2

4 3 2 1

 

附求排列和组合的代码:

 

 

using System;

public class CombinationPermutation

{

    public static void Main()

    {

        Console.WriteLine("combination");

        C(6,4);

        Console.WriteLine("permutation");

       P(4);

    }

    public static void PrintSeq(int[] s)

    {

        for(int i=0;i<s.Length;i++)

           Console.Write("{0,2}",s[i]);

        Console.WriteLine();

    }

    public static int Fac(int n)

    {

       int nRet=1;

        for(int i=2;i<=n;i++)

           nRet*=i;

        return nRet;

    }

    public static int CountC(int n, int r)

    {

        return Fac(n)/Fac(n-r)/Fac(r);

    }

    private static int[] seq={1,2,3,4,5,6};

   

    //algorithm of Permutation

    public static void P(int n)

    {

       int[] a=new int[n];

        for(int i=0;i<n;i++) a[i]=seq[i];

        PrintSeq(a);

       int nCount=Fac(n);

        for( int k=1;k<nCount;k++)

       {

           int m=n-2;

           while (a[m]>a[m+1]) m--;  

           int q=n-1;

           while(a[q]<a[m]) q--;

           int tmp;

           tmp=a[m];

           a[m]=a[q];

           a[q]=tmp;

          

           m=m+1;

           q=n-1;

           while (m<q)

           {

               tmp=a[m];

               a[m]=a[q];

               a[q]=tmp;

               q--;

               m++;

           }

           PrintSeq(a);

       }

    }

   

    //algorithm of Combination

    public static void C(int n, int r)

    {

       int[] a=new int[r];

        for(int i=0;i<r;i++)

           a[i]=seq[i];

        PrintSeq(a);

        for( int k=1;k<CountC(n,r);k++)

       {

           int max_val=seq[n-1];

           int m=r-1;

           while(a[m]==max_val)

           {

               m-=1;

               max_val-=1;

           }

           a[m]+=1;

           for(int j=m+1;j<r;j++)

               a[j]=a[j-1]+1;

           PrintSeq(a);

       }

    }

}

 

posted on 2004-11-20 19:24  星星之火  阅读(8673)  评论(4)    收藏  举报

导航