演算法01:全排列遞迴演算法
阿新 • • 發佈:2019-01-26
全排列是指n個元素按一定順序的所有排列組合,如{1,2,3}三個元素的全排列為{1,2,3}、{1,3,2}、{2,1,3}、{2,3,1}、{3,1,2}、{3,2,1}共3!種。
常見排列的演算法一般有:
(1)遞迴法
(2)字典序法
(3)鄰位對換法
(4)遞增進位制數法
(5)遞減進位制數法
具體介紹:
(1)遞迴法
如求{1,2,3,4}的全排列
1.先考慮最後一個數{4}的全排列p(4)={{4}}一種;
2.{3,4}的全排列p(3,4)={{3,4},{4,3}}兩種;
3.{2,3,4}的全排列p(2,3,4)=2p(3,4)+3p(2,4)+4p(2,3),依此類推。
演算法思路:
1.首先定義一個數組和一個交換陣列元素的函式
int list[] = {1,2,3,4} , n = 4;
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
2.遞迴函式的基本思想是:
(1)求1p(2,3,4),即以1開頭求出剩下的數{2,3,4}的全排列;
(2)為了求出2p(3,4)+3p(2,4)+4p(2,3),p(3,4)={{3,4},{4,3}},相當於把list陣列最後兩個元素交換,3p(2,4)又可以看成把3和2交換後求p(2,4),4p(2,3)是把4和3交換後求p(3,2);
(3)再求2p(1,3,4),相當於把2和1交換後求剩下數的全排列。
由此可得到遞迴函式,其中i為每次遞迴排列的第一個數的位置,k為要和第一個數交換的數的位置
void perm(int k) { int i; if(k >= n){ for(i = 0; i < n; i++) cout<<list[i]; cout<<endl; total++; }else{ for(i = k; i < n; i++){ swap(&list[k], &list[i]); perm(k+1); swap(&list[k], &list[i]); } } }
完整演算法:
#include <cstdlib>
#include <iostream>
using namespace std;
int list[100], n,total;
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void perm(int k)
{
int i;
if(k >= n){
for(i = 0; i < n; i++)
cout<<list[i];
cout<<endl;
total++;
}else{
for(i = k; i < n; i++){
swap(&list[k], &list[i]);
perm(k+1);
swap(&list[k], &list[i]);
}
}
}
int main()
{
while(cin>>n){
for(int i = 0; i < n;)
list[i] = ++i;
total = 0;
perm(0);
cout<<total<<endl;
}
system("PAUSE");
return 0;
}