刚看到求关于一道人称“暴难”的排列...我也有个想了两年都想不通的全排列问题想请教

163lzm 2003-12-04 12:32:38
用户输入N
输出N的全排列N!
如:
input 2
output 12
21

input 3
output 123
132
213
231
312
321
求不用穷举法的更好算法。
...全文
108 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
163lzm 2003-12-10
  • 打赏
  • 举报
回复
up
fryboy 2003-12-10
  • 打赏
  • 举报
回复
xuexi
163lzm 2003-12-09
  • 打赏
  • 举报
回复
up
MayhCat 2003-12-09
  • 打赏
  • 举报
回复
上面写错了,应是m!种...
MayhCat 2003-12-09
  • 打赏
  • 举报
回复
/* 求一个集合中m个元素的m种全排列 */
#include <stdio.h>
#include <conio.h>
#include <mem.h>
#define M 4 /* 集合中的元素个数 */

typedef struct
{
char data; /* 数据 */
int sel; /* 选中状态 */
}ELEMENT;

ELEMENT e[M+1]; /* 声明M个元素, 元素[0]保留 */
ELEMENT *path[M+1]; /* path记录当前经过的路径元素 */
int depth = 0; /* 指示调用的当前位置 */
int percount = 0; /* 记录共含排列次数 */

void search(void)
{
int i, j;

depth++;
for (i=1; i<=M; i++) /* 从初始排列最前的开始选一个未被选择过的元素 */
{
if (e[i].sel==0)
{
path[depth] = &e[i]; /* 记录当前位置的元素 */
e[i].sel = 1; /* 置已选中 */
if (depth<M) /* 搜索下一个位置 */
{
search();
}
else /* 一组排列已经确定 */
{
putch('{'); /* 打印 */
for (j=1; j<=M; j++)
putch((*path[j]).data);
printf("}\n");
getch();
e[i].sel = 0; /* 清除队尾元素的选中状态 */
percount++; /* 统计排列次数 */
break;
}
}
}
depth--; /* 返回到上个位置 */
(*path[depth]).sel = 0; /* 清除前一个元素选中状态 */
}

void main()
{
int i;
printf("\n");
for (i=1; i<=M; i++) /* 初使化, e[0]不用 */
{
e[i].data = i + '0';
e[i].sel = 0; /* 未被选中 */
printf("%c", e[i].data);
}
printf("\n");
search();
printf("count:%d", percount); /* 统计结果 */
getch();
}
wenxinfly 2003-12-07
  • 打赏
  • 举报
回复
用递归法做算不算?
我的代码是
请指#include<iostream.h>
#include<fstream.h>
#include<stdlib.h>
#include<string.h>
void permute(int a[],int s,int n)
{
ofstream fout("outfile",ios::app);
int i,temp;

if(s==n)
{
for(i=1;i<=n;i++)
{
cout<<a[i];
fout<<a[i];
}
fout<<endl;


cout<<endl;
}
else
for(i=s;i<=n;i++)
{
temp=a[s];a[s]=a[i];a[i]=temp;

permute(a,s+1,n);
temp=a[s];a[s]=a[i];a[i]=temp;




}
}
void main()
{
int a[100],n;
cout<<"input the number n:";
cin>>n;
for(int i=1;i<=n;i++)
a[i]=i;
permute(a,1,n);
cout<<endl;
}

请指教!!!!
ZhangYv 2003-12-05
  • 打赏
  • 举报
回复
好久没看见楼上的身影了:)
163lzm 2003-12-05
  • 打赏
  • 举报
回复
thanks
one_add_one 2003-12-05
  • 打赏
  • 举报
回复
for(i=0;i<n;i++) a[i]=i;

void pp(int d)
{
if(d==n) { for(i=0;i<n;i++) cout<<a[i]; return; };
for(i=d;i<n;i++)
{
swap(a[d],a[i]);
pp(d+1);
swap(a[d],a[i]);
}
}
gushaoping 2003-12-05
  • 打赏
  • 举报
回复
本人完全赞同one_add_one的如下一段程序,采用递归回溯的思想,

每次把第i号元素与与后面的i+1,i+2,...,n交换,交换后再递归调用本身求解,

当排出了N个的时候便输出一组解.i 初值为1

#define N 9
int a[N+1];

void pp(int d)
{
if(d==n) { for(i=0;i<n;i++) cout<<a[i]; return; };
for(i=d;i<n;i++)
{
swap(a[d],a[i]);
pp(d+1);
swap(a[d],a[i]);
}
}
void main()
{
for(int i=1;i<=N;i++) a[i]=i;
pp(1);
}
swap函数单独定义.此略
caohoujie 2003-12-05
  • 打赏
  • 举报
回复
楼上的楼上的方法太老套了点吧
void permute(int *p,bool *used,int pos,const int& n,const int& r)
{
int i;
/*如果已排好r个元素了,则可打印r个元素的排列 */
if (pos==r)
{
for (i=0; i<r; i++)
cout << (p[i]+1);
cout << endl;
return;
}
for (i=0; i<n; i++)
if (!used[i])
{ /*如果第i个元素未用过*/
/*使用第i个元素,作上已用标记,目的是使以后该元素不可用*/
used[i]=true;

/*保存当前搜索到的第i个元素*/
p[pos] = i;

/*递归搜索*/
permute(p,used,pos+1,n,r);

/*恢复递归前的值,目的是使以后改元素可用*/
used[i]=false;
}
}
上面的方法也并不一定好,有什么更好的方法吗?
shadowboxing 2003-12-04
  • 打赏
  • 举报
回复
《组合数学》书上有的
我记得是从1开始,数字上标上向左或向右的箭头,根据规则移动的,
反复移动之后就全排出来了。
hanyixin 2003-12-04
  • 打赏
  • 举报
回复

看组合数学的书,讲的很详细,这是我们的一个考题 ^_^

wlpwind 2003-12-04
  • 打赏
  • 举报
回复
一般有四种:
(A)字典序法
(B)递增进位制数法
(C)递减进位制数法
(D)邻位对换法

举例 :
字典序排列算法
1.给出初始排列:p1=1,2,3,4,…,n
2.若pk已定义 (1≤k≤n!-1)
pk=a1,a2,…,am,…,an
则按下列规定,定义pk的下一个排列
pk+1=b1,b2,…,bm,…,bn
(1)寻找am:m=max{j|aj<aj+1}
即am,am+1是最右面的顺序,自am+1开始均为 逆序。
(2)给出bi(i=1,2,…,n)
a)第m项之前的项不变:
b1=a1,b2=a2,…,bm-1=am-1
b)bm=min{ap|ap>am,p>m)
即在am右面大于am的项中选取最小的项作为bm。 c)把am,am+1,…,ap-1,ap+1,…,an从小到大排列,送入bm+1,bm+2,…,bn。


wlpwind 2003-12-04
  • 打赏
  • 举报
回复
组合数学书上有生成排列的算法。
ThenLong 2003-12-04
  • 打赏
  • 举报
回复
第归
短歌如风 2003-12-04
  • 打赏
  • 举报
回复
type
TIntAry = array [0..32767] of Integer;
PIntAry = ^ TIntAry;

procedure Swap(var a, b: Integer);
var
c: Integer;
begin
c := a;
a := b;
b := c;
end;
procedure Reverse(Data:PIntAry; Len: Integer);
var
I, J: Integer;
begin
I := 0;
J := Len - 1;
while I < J do
begin
Swap(Data[I], Data[J]);
Inc(I);
Dec(J);
end;
end;
function NextPermutation(Data:PIntAry; Len: Integer): Boolean;
var
I: Integer;
J: Integer;
K: Integer;
Completed: Boolean;
begin
if (Len < 2) then
Result := False
else
begin
I := Len - 1;
Completed := False;
while not Completed do
begin
J := I;
Dec(I);
if Data[I] < Data[J] then
begin
K := Len;
repeat
Dec(K);
until Data[I] < Data[K];
Swap(Data[I], Data[K]);
Reverse(@Data[J], Len - J);
Result := True;
Completed := True;
end
else if I = 0 then
begin
Reverse(Data, Len);
Result := False;
Completed := True;
end;
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
type
TData = array[0..3] of Integer;
const
Data: TData =
(1,2,3,4);
function AryToStr(var D: TData): String;
begin
Result := Format('%d,%d,%d,%d', [d[0],d[1],d[2],d[3]]);
end;
var
a: TData;
begin
A := Data;
repeat
Memo1.Lines.Add(AryToStr(a));
until not NextPermutation(@a, Length(a));
end;
saint001 2003-12-04
  • 打赏
  • 举报
回复
http://expert.csdn.net/Expert/topic/2495/2495045.xml?temp=.1706201
我总结的排列组合生成算法的实现
N是不固定的
laughcry2002 2003-12-04
  • 打赏
  • 举报
回复
以上算法本质上都是穷举法。似乎不可能存在“不穷举的算法”
163lzm 2003-12-04
  • 打赏
  • 举报
回复
十分感谢,特别是ZhangYv(英语-痛苦、绝望)
但未能结贴,我要的N不是固定的.
FAQ上的是固定的(预先define N =4)
继续请教.
加载更多回复(1)

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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