求一算法输出n个数的全排列

xs52121 2005-12-18 12:29:55
比如123输出123,321,132,312,213,231,要是n个怎么写这个程序
...全文
3719 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
gangzichh 2005-12-20
  • 打赏
  • 举报
回复
我也学习吧
xs52121 2005-12-19
  • 打赏
  • 举报
回复
多谢大家 我也好好调试一下
xiaocai0001 2005-12-18
  • 打赏
  • 举报
回复
递归

[排列] 通常我们希望检查n 个不同元素的所有排列方式以确定一个最佳的排列。
比如,a,b 和c 的排列方式有:a b c, a c b, b a c, b c a, cab 和c b a。n个元素的排列方式共有n!种。由于采用非递归的C + +函数来输出n 个元素的所有排列方式很困难,所以可以开发一个递归函数来实现。令E= {e1 , ..., en }表示n 个元素的集合,我们的目标是生成该集合的所有排列方式。令Ei 为E中移去元素i 以后所获得的集合,perm (X) 表示集合X 中元素的排列方式,ei . p e r m(X)表示在perm (X) 中的每个排列方式的前面均加上ei 以后所得到的排列方式。例如,如果E= {a, b, c},那么E1= {b, c},perm (E1 ) = ( b c, c b),e1 .perm (E1) = (a b c, a c b)。
对于递归的基本部分,采用n = 1。当只有一个元素时,只可能产生一种排列方式,所以
perm (E) = ( e),其中e 是E 中的唯一元素。当n > 1时, perm (E) = e1 .perm (E1 ) +e2 .perm(E2 ) +e3.perm (E3) + … +en .perm (En )。这种递归定义形式是采用n 个perm (X) 来定义perm (E), 其中每个X 包含n- 1个元素。至此,一个完整的递归定义所需要的基本部分和递归部分都已完成。
当n= 3并且E=(a, b, c)时,按照前面的递归定义可得perm (E) =a.perm ( {b, c} ) +b.perm ( {a,
c} ) +c.perm ( {a, b} )。同样,按照递归定义有perm ( {b, c} ) =b.perm ( {c} ) +c.perm ( {b}), 所以a.perm ( {b, c} ) = ab.perm ( {c} ) + ac.perm ( {b}) = a b . c + ac.b = (a b c, a c b)。同理可得
b.perm ( {a, c}) = ba.perm ( {c}) + bc.perm ( {a}) = b a . c + b c . a = (b a c, b c a),c.perm ( {a, b}) =ca.perm ( {b}) + cb.perm ( {a}) = c a . b + c b . a = (c a b, c b a)。所以perm (E) = (a b c, a c b, b a c, b c a,c a b, c b a)。注意a.perm ( {b, c} )实际上包含两个排列方式:abc 和a c b,a 是它们的前缀, perm ( {b, c} )是它们的后缀。同样地,ac.perm ( {b}) 表示前缀为a c、后缀为perm ( {b}) 的排列方式。
程序1 - 1 0把上述perm (E) 的递归定义转变成一个C++ 函数,这段代码输出所有前缀为l i s t [ 0:k-1], 后缀为l i s t [ k:m] 的排列方式。调用Perm(list, 0, n-1) 将得到list[0: n-1] 的所有n! 个排列方式,在该调用中,k=0, m= n - 1,因此排列方式的前缀为空,后缀为list[0: n-1] 产生的所有排列方式。当k =m 时,仅有一个后缀l i s t [ m ],因此list[0: m] 即是所要产生的输出。当k<m时,先用list[k] 与l i s t [ k:m] 中的每个元素进行交换,然后产生list[k+1: m] 的所有排列方式,并用它作为list[0: k] 的后缀。S w a p是一个inline 函数,它被用来交换两个变量的值,其定义见程序1 -11。P e r m的正确性可用归纳法来证明。

template <class T>
inline void Swap(T& a, T& b)
{// 交换a和b
T temp = a;
a = b;
b = temp;
}

template<class T>
void Perm(T list[], int k, int m)
{//生成list [k:m ]的所有排列方式
int i;
if (k == m)
{//输出一个排列方式
for (i = 0; i <= m; i++)
cout << list [i];
cout << endl;
}
else // list[k:m ]有多个排列方式
// 递归地产生这些排列方式
for (i=k; i <= m; i++)
{
Swap (list[k], list[i]);
Perm (list, k+1, m);
Swap (list [k], list [i]);
}
}
Mr_Yang 2005-12-18
  • 打赏
  • 举报
回复
学习。
greenteanet 2005-12-18
  • 打赏
  • 举报
回复
楼上几位兄弟给出了一些参考答案啦。我觉得楼主用递归可以解决你给出的问题。不过考虑到效率,楼主可以要用一些条件来限制同一个排列中元素的值。
cunsh 2005-12-18
  • 打赏
  • 举报
回复
/*
例4:将1到N的N个自然数排成一列,共有1*2*3……*N种不同的排列方法,如N=3时,有6种排列方案,分别为123,132,213,231,312,321.试编程序输出1到N的全部排列,假设N<10.
为了设计出由计算机输出1到N的全部排列程序,就必须寻找不同排列之间的规律.通过观察N=5(参见本例的运行结果)的排列情况,可以发现,如果把每个排列看作一个自然数,则所有排列对应的数是按从小到大的顺序排列,从当前的排列产生下一个排列时必然会造成某一位置上的数字变大,这一位置显然应该尽量靠右,并且在它左边位置上的数字保持不变,这就意味着这一位置变成的数字来自于它的右边, 并且变大的幅度要尽可能小,也就是说在它右边如有几个数同时比它大时,应该用其中最小的来代替它.由于这一位置是满足上述条件的最右边的一位,所以在它右边的所有数字按逆序排列,即在这些数字的右边没有一个大于它的数.程序中先从右至左找到第一个位置,该位置上的数比它右边的数小,这个位置就是所要找的满足上述条件的位置,然后再从右到左找到第一个比该位置上的数字大的数字所在的位置,将这两个位置上的数字交换,再将该位置右边的所有元素颠倒过来,即将它们按从小到大的顺序排列,就得到了下一个排列.


结果应该是:
Input n:5
12345 12354 12435 12453 12534 12543 13245 13254 13425 13452
13524 13542 14235 14253 14325 14352 14523 14532 15234 15243
15324 15342 15423 15432 21345 21354 21435 21453 21534 21543
23145 23154 23415 23451 23514 23541 24135 24153 24315 24351
24513 24531 25134 25143 25314 25341 25413 25431 31245 31254
31425 31452 31524 31542 32145 32154 32415 32451 32514 32541
34125 34152 34215 34251 34512 34521 35124 35142 35214 35241
35412 35421 41235 41253 41325 41352 41523 41532 42135 42153
42315 42351 42513 42531 43125 43152 43215 43251 43512 43521
45123 45132 45213 45231 45312 45321 51234 51243 51324 51342
51423 51432 52134 52143 52314 52341 52413 52431 53124 53142
53214 53241 53412 53421 54123 54132 54213 54231 54312 54321



/*


#include<iostream>
using namespace std;

void main(){
int n; //n个数字的排列;
cout<<"input:";
cin>>n;
int *p=new int[n]; //数组保存各位数字;
for(int i=0;i<n;i++) //初始化为第一个排列;
p[i]=i+1;
do{
for(i=0;i<n;i++) //输出排列中的数字
cout<<p[i]<<" ";
cout<<endl;
for(int j=n-1;j>0;j--) //从右向左;找要交换的位置1(j);
if(p[j]>p[j-1]) break;
if(j==0)break; //找不到要交换的位置.退出do
j--;
for(int k=n-1;k>j;k--) //在位置1右边;从右向左;
//找要交换的位置2(k);
if(p[k]>p[j])break;
swap(p[k],p[j]); //交换位置1和位置2的值;
//把位置1后边的所有位反序排列;
for(int x=j+1,y=n-1;x<y;x++,y--)
swap(p[x],p[y]);
}while(1);
delete []p;
}
sms88 2005-12-18
  • 打赏
  • 举报
回复
#include<stdio.h>
#define M 3 //对1,2,...M间的数进行全排列
int B[M];

void pailie(int n)
{
if( n == 1 )
{
for(int j = 0 ; j < M ; j++ )
{
printf("%d ",B[j]);
}
printf("\n");
}
for( int i=1 ; i <=n ; i++ )
{
int a=B[i-1]; //----(a)
B[i-1]=B[n-1];
B[n-1]=a;
pailie(n-1); //递归调用
a=B[n-1];
B[n-1]=B[i-1];
B[i-1]=a; //--- (b)
}
}


int main()
{
for(int i=0;i<M;i++)
B[i]=i+1;
pailie(M);
return 0;
}

happydivid 2005-12-18
  • 打赏
  • 举报
回复
哈哈,我有现成的:
利用递归函数进行数组的全排列。
算法思想:
每次确定一个元素作为排列的第一个元素,然后对剩下的元素进行全排列并与已确定元素构成整个数组的全排列。
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

int LENGTH; //数组的长度
int Line=1; //用来作输出的格式控制标志
int TOTAL=0; //全排列的总数
char *Array; //用来辅助输出的全局数组

void Swap(char &ch1, char &ch2); //交换两个单元的值的函数
void ArraySort(char array[], int n); //进行全排列的递归函数

void main()
{
//得到数组长度
cout<<"请输入数组的长度(建议>1 && <10): ";
cin>>LENGTH;

//得到格式化输出标志
for ( int j=2; j<LENGTH; j++ )
Line*=j;

//数组的初始化
Array=new char[LENGTH+1];
char *array=new char[LENGTH];

for ( int i=0; i<LENGTH; i++ )
array[i]='A'+i;

//调用递归函数并输出
ArraySort( array, LENGTH );
cout<<"\nTotal:"<<TOTAL<<endl<<endl;

delete [] Array;
delete [] array;
system("pause");
}

void Swap(char &ch1, char &ch2)
{
ch1+=ch2;
ch2=ch1-ch2;
ch1-=ch2;
}

void ArraySort(char array[], int n)
{
//递归的终止点,只要数组中的元素个数为1,则结束递归并输出一个排列
if ( n==1 )
{
Array[LENGTH-n]=array[0]; //将数组中的最后一个元素放入输出数组
Array[LENGTH]='\0';
cout<<Array<<'\t';
TOTAL++;
if ( !(TOTAL%Line) )
cout<<"\n--------------\n";
return ;
}

//为了保证初始数组array不变,构建临时数组T_array代替
char *T_array=new char[n];

for ( int i=0; i<n; i++ )
{
//将array数组赋给T_array
int j;
if ( i==1 )
goto Nochange;
for ( j=0; j<n; j++ )
T_array[j]=array[j];

if ( i==0 )
{
Array[LENGTH-n]=T_array[0];
ArraySort( &T_array[1], n-1 );
continue;
}
Nochange:
//将数组中第一个元素与第i元素交换,并放入输出数组中,达到排列的目的
Swap( T_array[0], T_array[i] );
Array[LENGTH-n]=T_array[0];

//调用递归函数进行除T_temp[0]外所有函数的全排列
ArraySort( &T_array[1], n-1 );
}

delete [] T_array; //释放临时数组T_array,防止泄漏
}
goodluckyxl 2005-12-18
  • 打赏
  • 举报
回复
求一算法输出n个数的全排列
//看看《C语言的科学与》艺术有对递归关于你的这个需求类似的解法
sankt 2005-12-18
  • 打赏
  • 举报
回复
学习

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧