有关排列组合的算法(200分)

  • 主题发起人 主题发起人 圣诞快乐
  • 开始时间 开始时间

圣诞快乐

Unregistered / Unconfirmed
GUEST, unregistred user!
寻求有关排列组合的算法:
123:123,132,213,231,312,321
向各位大虾讨教,奉上200分,不胜感激。
 
◇ 排列组合
-------------------------------------------------------------------------------- -------------------------------------------------------------------------
NCTU-CIS BBS `programming' 版 精华区
■■■ 排列组合 ■■■
-------------------------------------------- 整理:william@cis_nctu -----
-------------------------------------------------------------------------
发信人: PaladinMu@cis_nctu (Paladin), 信区: programming
标 题: 1 to n 之排列问题
发信站: 交大资科_BBS (May 25 22:33:13 1994)
转信站: cis_nctu
> 请问列出由 1 到 N 的所有排列组合的演算法?
> 请用 C 和 LISP 写出。谢谢!
提供一个 functional 的解答.
首先写一个函数 (interleave a xs), 把 a 给插到 xs 的所有空隙.
例如 (interleave 4 '(1 2 3)) => ((4 1 2 3) (1 4 2 3) (1 2 4 3) (1 2 3 4))
Interleave 怎麽写呢? 用这样的递回关系: 把 a 插到 xs 的每一个空隙, 其实就是
把 a□□□胪@个空隙, 或著把第一个空隙留给 (car xs), 把 a 往 (cdr xs)
的空隙里面插.
(defun interleave (a xs)
(if (null xs)
(list (list a))
(cons (cons a xs) ;
a放第一个
(mapcar #'(lambda (ys) (cons (car xs) ys)) ;把第一个留出来
(interleave a (cdr xs)) ;
往(cdr xs)里找空隙
))
))
有了 interleave, 写所有的排列 (permutation xs) 就方便了. 如果我们
已经算出了 (permutation (cdr xs)), 把 (car xs) 插到每一个空隙里就可以了.
(defun permutation (xs)
(if (null xs)
'(())
(apply #append
(mapcar #'(lambda (ys) (interleave (car xs) ys))
(permutation (cdr xs))
))
))
=============================================================================
发信人: ddh.bbs@bbs.ntu (恋琴男孩), 信区: programming
标 题: 对 n 个字排列组合..by recursive..
发信站: 台大计中椰林风情站 (Wed Aug 2 09:42:37 1995)
转信站: cis_nctu!news.cis.nctu!news.csie.nctu!netnews.ntu!Palmarama
/*******************************************/
/* 本程式无法判别字串中相同字时出现的重复 */
/* 情形;请自行修改!! */
/*******************************************/
int num,j=1,level=0,a[15];
char ch[15],out[15];
tt()
{
int i;
level+=1;
for(i=0;i<num;i++)
if(a==0)
{
a=1;
out[level-1]=ch;
if(level==num)
printf("/n%3d %s",j++,out);
tt();
a=0;
}
level-=1;
}
main()
{
num=0;
/*number of input*/
printf("/nInput characters:");
while((ch[num]=getche())!='/r')
{
a[num]=0;
num+=1;
}
ch[num]='/0';
/*end character*/
tt();
}

 
创建一个函数
function insertanypos(str1, str2 : string): Tstrings;
str1长度为1,str2长度不限
目的:把str1插入到str2的任何位置(一个循环搞定)
返回一个Tstrings;
调用这个函数的地方:
先取母串的第一个为str2参数,母串的第二个为str1参数,调用函数insertanypos
返回的结果到一个临时的列表(Tstrings)
然后循环的调用列表里的每一项和母串的第3,4,5,6,7....个字符进行insertanypos
程序代码过一会儿再给你!
(*这个方法可以适用于字符模式*)
 
谢谢tseug。奉上200分
 
真是不甘!以下是我的程序
你不妨试一下,在from上放一个button, Tlistbox, Tlabel, Tedit;
你要排列的字符串就放在edit1里面
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
ListBox1: TListBox;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
function insertanypos(str1, str2: string): Tstrings;
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
i,x: integer;
tmpstrs,mainstrs: Tstrings;
begin
i := 2;
tmpstrs := Tstringlist.Create;
mainstrs := insertanypos(edit1.text[2], edit1.text[1]);
while i <= length(edit1.text) do
begin
tmpstrs.Clear;
tmpstrs.addstrings(mainstrs);
mainstrs.clear;
inc(i);
for x := 0 to tmpstrs.count - 1 do
begin
mainstrs.addstrings( insertanypos(edit1.text, tmpstrs[x]));
end;
end;
listbox1.items := tmpstrs;
label1.Caption := inttostr(tmpstrs.count);
tmpstrs.Free;
end;

function Tform1.insertanypos(str1, str2: string): Tstrings;
var
i: integer;
tmpstr: string;
begin
result := Tstringlist.create;
result.add(str2+str1);
for i := 0 to length(str2) - 1 do
begin
tmpstr := copy(str2, 1, i) + str1 + copy(str2, i + 1, length(str2) - i);
result.add(tmpstr);
end;
end;

end.

 
很感激eric.youbin乐于助人的精神,提出问题不久我就想到了解决办法,
本来想取消问题,收回银子,看到tseug的回答,思路差不多,就付了银子。
刚付了银子,就看到您的回复,可惜银子已空。
悔也,无有银子,只能在此言谢。
 
不用客气!
 
to :eric.youbin
你的算法算出的是P(n,n),比如P(6,6)=720,请问:
P(m,n)怎以写?比如:P(6,4)
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
603
import
I
I
回复
0
查看
473
import
I
后退
顶部