zoukankan      html  css  js  c++  java
  • 组合序列、排列序列的生成实现

    组合序列、排列序列的生成实现

             前面我们已经讨论了关于组合数、排列数的生成《排列、组合的计算》,并没有涉及组合序列和排列序列是如何生成的。这里我们将讨论序列和排列序列是如何生成的,首先我们讨论组合序列。

    一、组合序列

    假如有如下集合(注意,集合中的元素是互异的):

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9

             我们从该集合中选取3个元素,问有多少种组合,这些组合具体是什么?

             首先,我们给出程序如下:

    // 组合序列的生成
    #include <iostream>
    #include <vector>
    using namespace std;
    
    void comb(const vector<int>& arr, int beg, int m, vector<vector<int> >& coms, vector<int>& tmp, int& total)
    {
        if (m > arr.size() - beg)
        {
            return;
        }
        if (m == 0)
        {
            coms.push_back(tmp);
            ++total;
        }
        else
        {
            tmp.push_back(arr[beg]);
            comb(arr, beg+1, m-1, coms, tmp, total);
            tmp.pop_back();
            
            comb(arr, beg+1, m, coms, tmp, total);
        }
    }
    
    int main()
    {
        int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        vector<int> arr(a, a + sizeof (a) / sizeof (*a));
        
        vector<vector<int> > coms;
        vector<int> tmp;
        int total = 0;
        comb(arr, 0, 4, coms, tmp, total);
        
        for (vector<vector<int> >::size_type i = 0; i != coms.size(); ++i)
        {
            for (vector<int>::size_type j = 0; j != coms[i].size(); ++j)
            {
                cout << coms[i][j] << ' ';
            }
            cout << endl;
        }
        cout << coms.size() << endl;
        cout << total << endl;
        
        system("PAUSE");
        return 0;
    }

             程序的算法是根据组合的特性而得的:C(N, M) = C(N-1, M-1) + C(N-1, M)。

             程序运行的实例为:C(10, 4) = 210,组合数也可以根据之前的程序用公式得到。

    二、排列序列

    有集合:

    0, 1, 2, 3, 4, 5, 6, 7, 8, 9

             求该集合的排列。

             根据排列的性质A(N, M) = N*A(N-1, M-1)。

             我们利用这个性质用递归实现:

    // 排列递归实现
    #include <iostream>
    #include <vector>
    using namespace std;
    
    void exchange(int& a, int& b)
    {
        int t = a;
        a = b;
        b = t;
    }
    
    void
    perm(
      const vector<int>& arr_
    , int n
    , int beg
    , vector<vector<int> >& pers
    , vector<int>& tmp
    , int& total
    )
    {
        static vector<int> arr(arr_);
        if (n == 0)
        {
            pers.push_back(tmp);
            ++total;
        }
        for (int i = beg; i != arr.size(); ++i)
        {
            exchange(arr[beg], arr[i]);
            tmp.push_back(arr[beg]);
            perm(arr, n-1, beg+1, pers, tmp, total);
            tmp.pop_back();
            exchange(arr[beg], arr[i]);
        }
    }
    
    int main()
    {
        int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        vector<int> arr(a, a + sizeof (a) / sizeof (*a));
        vector<bool> flags(arr.size(), false);
        vector<vector<int> > pers;
        vector<int> tmp;
        int total = 0;
        perm(arr, 3, 0, pers, tmp, total);
        
        for (vector<vector<int> >::size_type i = 0; i != pers.size(); ++i)
        {
            for (vector<int>::size_type j = 0; j != pers[i].size(); ++j)
            {
                cout << pers[i][j] << ' ';
            }
            cout << endl;
        }
        cout << pers.size() << endl;
        cout << total << endl;
        
        system("PAUSE");
        return 0;
    }

             程序的实现逻辑为:根据排列公式A(n, m) = n*A(n-1, m-1),对当前位置取n个元素,然后递归计算后面的A(n-1, m-1)。所以得到以上。

             当arr为:

    1, 2, 3, 4, 5, 6

             时,求其全排列为:

    三、总结

         以上对组合序列和排列序列的生成程序进行了讨论。实质上就是根据组合的性质:

    C(N, M) = C(N-1, M-1) + C(N-1, M)

    以及排列的性质:

           A(N, M) = N * A(N-1, M-1)

    利用递归的方式进行求解。

             由于组合公式中只是相加的方式,所以递归程序中不存在直接的循环。排列公式中存在变量N,所以在实际的实现种需要有直接的循环进行体现。

             什么时候使用递归,如何使用递归,将在下一篇种进行介绍。

             另外,关于组合、排列的程序实现,可以进行进一步的封装。我们这里没有进行进一步的封装。如果封装,有如下接口:

             组合:void comb(const vector<int>& arr, int m, vector<vector<int> >& coms, int& total);

             排列:void perm(const vector<int>& arr, int m, vector<vector<int> >& pers, int& total);

             全排列:void full_perm(const vector<int>& arr, vector<vector<int> >& pers, int& total);

  • 相关阅读:
    用SecureCRT来上传和下载文件
    Linux指令--tar,gzip
    Linux指令--文件和目录属性
    Linux指令--which,whereis,locate,find
    Linux指令--head,tail
    Linux指令--more,less
    Linux指令--nl
    Linux指令--cat,tac
    Linux指令--touch
    Linux指令--cp
  • 原文地址:https://www.cnblogs.com/unixfy/p/3161810.html
Copyright © 2011-2022 走看看