排列組合算法


題目:求(1)一組數字的全排列(2)一組數字中某幾個數字的組合

一、排列算法:

全排列是將一組數按一定順序進行排列,如果這組數有n個,那么全排列數為n!個。現以{1, 2, 3}為例說明如何編寫全排列的遞歸算法。 如下圖所示:

 

 

 


上圖中,第一層S1表示第一個數分別與第1、2、3個數交換位置,如123是1和第一個數1交換,213是1和第二個數2交換,321是1和第三個數交換。第二層S2是第二個數分別與第2、3個數交換位置。則最后一層的所有葉子節點,即為全排列的所有結果。第k層中的節點Sk就是父節點中的第k個數,分別與第k、k+1...n個數交換位置。

遞歸算法代碼:

 

#include <iostream>

int n =0;

void swap( int* a,int* b)

{

    int m;

    m = *a;

    *a = *b;

    *b = m;

}

 

void perm(int list[],int k,int m)

{

    int   i;

    if(k > m)

    {

        for (i = 0; i <= m; i++)

        {

            printf("%d ", list[i]);

        }  

        printf( "\n" );

        n++;

    }

    else

    {

        for(i = k; i <= m; i++)

        {

            swap(&list[k], &list[i]);

            perm(list, k + 1, m);

            swap(&list[k], &list[i]);

        }

    }

}

 

int main()

{

    int list[] = { 1 , 2 , 3 , 4 , 5};

    perm(list, 0 , 4);

    printf("total:%d\n", n);

    return 0 ;

}

 

 

 

二、組合算法:
組合就是從n個數中選m個數的所有組合。(n>=m)
利用遞歸的思想,假設從n=4,m=2,數組a{1,2,3,4},則算法思想如下圖所示:

 

 

上圖中,第一層S1中的節點是數組中的所有數字,第二次S2中的節點是分別從父節點的下一個位置開始。因為這個例子中m=2,所以共有2層。從第一層到第二層,深度遍歷這顆樹,即可得到所有組合。
遞歸算法代碼:

#include <vector>

#include <iostream>

using namespace std;

void Comb(int index,int begin,int len,int n,int * A,int* C);

int main()

{

  int A[5] = {1,2,3,4,5};

  int len =5, n =3;

  int* C =new int[n +1];

  Comb(0,0, len, n, A, C);

  delete[]C;

  return 0;

}

//遞歸組合

void Comb(int index,int begin,int len,int n,int * A,int * C)

{

  // index表示某個組合中的索引,begin表示從數組A中begin位置開始尋找,

  // len表示數組A長度,n表示組合中個數,A表示原數組,C表示組合數組

  if(index == n)

  {

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

    {

      cout << C[i] <<"";

    }

    cout << endl;

    return ;

  }

  for(int j = begin; j <= len - n + index; j++)

  {

    C[index] = A[j];

    Comb(index +1, j +1, len, n, A, C);

  }

}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM