您的位置:首页 > 其它

如何得到有重复元素的不重复全排列

2012-03-23 16:42 176 查看
M个元素中含有相同的元素,如何得到他们的全排列(不重复排列)?

元素表述: a1,a1,...a1, a2,a2,...a2,.......,an,an,...an

其中,a1的个数为N1, a2的个数为N2,以此类推,总个数为M。

则可以证明不重复的排列种类的数目: M!/(N1!*N2!*...*Nn!)

就是将N个数字做全排列。不过对于某些数字不能选择而已。

这里只要限制将要选择的数字必须大于原来已经选择的数字就可以达到目标。

下面是递归算法

#include <stdio.h>
#define   N   5

void   arrange(int   rec[],int   used[],int   depth);
void   write(int   rec[],   int   maxdepth);
int   a
={1,1,2,2,3};   //这些值必须升序排列且大于0
int   count=0;

int   main()
{int   rec[N+1]={0},used[N+1]={0};

arrange(rec,used,0);
printf( "\ncount=%d ",count);
getchar();
return   0;
}

void   write(int   rec[])
{   int   i;
for(i=0;i <N;i++)
printf( "%4d ",a[rec[i]]);
printf( "\n ");
count++;
}

void   arrange(int   rec[],int   used[],int   depth)
{
int   i,found_num;
if   (depth> =N)   write(rec);   //找到了一个可行解,输出
else
{found_num=0;               //增加这个变量记录原来本结点存储的数字
for(i=0;i <N;i++)     //   搜索该结点的孩子结点
{//如果该下标在前面还没有使用过,且该下标所指示的数字比
//原先所放置的数字要大,则是一个部分解
if(used[i]==0   &&   a[i]> found_num   )
{   rec[depth]=i;       //记录下该结点放置的下标
found_num=a[i];   //记录下本结点存放的数字
used[i]=1;             //   标记该下标已经被使用
arrange(rec,used,depth+1);       //   扩展,进入孩子结点继续搜索
used[i]=0;           //退回来后要清除本结点所记录下标的使用记录
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐