一个有关程序运行速度的问题!!!(巨难!)(100分)

  • 主题发起人 主题发起人 xysir001
  • 开始时间 开始时间
X

xysir001

Unregistered / Unconfirmed
GUEST, unregistred user!
代码如下:
procedure TForm1.Button2Click(Sender: TObject);
var
r,i,j,k,m,flag:integer;
CombStr,temp1,temp2,temp3:string;
uball:string;
begin
r:=strtoint(edit2.Text)
//组合C(n,r)中的r,即组合数;n通过计算原始数据个数得出,(在这个程序中r=3,n为500左右)
try
for i:=n-1 downto r-1 do
begin
temp1:=memo1.Lines.Strings
//temp1存放第一个数
for j:=i-1 downto r-2 do
begin
temp2:=memo1.Lines.Strings[j]
//temp2存放第二个数
for k:=j-1 downto 0 do
begin
temp3:=memo1.Lines.Strings[k]
//temp3存放第三个数
CombStr:=temp1+' '+temp2+' '+temp3
//CombStr为新组合的数
flag:=0;
uball:='';
for m:=0 to memo4.Lines.Count-1 do
if flag<8 then
if not AnsiContainsText(CombStr,memo4.Lines.Strings[m]) then
//memo4控件中的数据为标准数据,即memo4.Lines.Strings[m]与CombStr比较,如果不同,则保存
//memo4.Lines.Strings[m]数据,如下:uball:=uball+memo4.Lines.Strings[m]+' ';
begin
uball:=uball+memo4.Lines.Strings[m]+' ';
flag:=flag+1
//flag为记录保存数据的个数
end;
if flag=3 then
if not AnsiContainsText(memo2.Lines.Text,uball) then
//如果待保存的数据(uball)与memo2控件中数据相同,则不保存;memo2控件为保存满足条件的数据

memo2.Lines.Add(uball);

end;
temp3:='';

end;
temp2:='';
end;
temp1:='';

CombStr:='';
finally
application.MessageBox('完成!','提示',mb_ok)
end;
end;

为了能使程序能运行下去,我用了线程(这段代码中没有),但在:
  n=106,r=3,用了20多分钟;
  n=250,r=3,用了5个多小时;
  n=530,r=3,用了一晚上也没运算完。
这样的运算速度实在太慢,能不能对上面的代码进行优化或者采用其他的方法来提高运算速度。希望哪位朋友能帮忙解决。(如果我说的还不清楚,希望QQ联系,QQ:121269032)
谢谢!
谢谢!!
谢谢!!!


 
不要在循环里放可以提到外面的语句。
判断循环终值,把大的放到里面。
 
因为代码不全,别的没发现什么,至少有一个地方可优化的。
memo2.Lines.Add(uball);//??
注意:对于控件操作,因为显示刷新等问题很费时间的
建议先把uball放在一个TStrings变量中,所有工作完后再用Assign 指定到memo2中。
这样可以节省大量的时间。
 
太多判断在循环中!
 
要实现什么功能啊?看到都晕了
 
我看你好像在生成个密码字典,看样子!:)
yostgxf兄弟说的对,memo2.Lines.Add(uball);是个速度瓶颈所以应该在内存里实现,这样不涉及到刷新问题,如果实在想看进度,你可以放个ProgressBar,生成100个数字走一个格子。
还有,多线程是无法提高密码产生速度的,纯粹穷举解密不可取,你想生成个8位密码肯定需要一天以上时间的。应该先搜索待解密方的有关信息(单位名称、生日、门派号码、电话号码)然后通过程序互相组合生成一个密码字典、这样可以大大提高解密速度,祝你好运!:)
 
yostgxf:
  在我优化后的程序中,用的是TStrings。但速度还是有点慢,我昨天试了一下,在
n=500,r=3时,用了3个多小时。

希望各位大富翁能帮忙!
 
因为代码不全,不太好说。
1,上面的兄弟说了,的确控件刷新很浪费时间。
2,string有内存限制,如果你的数很大呢?
3,你用flag:=flag+1,为什么不用inc(flag),你隐藏额外开销了一个try..finally模块。
等等。。。
最好重新设计你的算法数据结构,上面的结构不是很好,祝你好运!
 
哈哈,还是进步不小啊。
1.在上面代码中可以取消temp1,temp2,temp3三个变量
temp3:=memo1.Lines.Strings[k]
//temp3存放第三个数
CombStr:=temp1+' '+temp2+' '+temp3
//CombStr为新组合的数
改为:CombStr:=memo1.Lines.Strings+。。。

减少赋值过程。
2.楼上的建议 flag:=flag+1,改用inc(flag),
3.能否优化AnsiContainsText(memo2.Lines.Text,uball) 函数
4.看看算法结构,有没有重复循环
祝成功!
 
已经将上面各位大富翁的建议都试了一遍,但速度提高不是很大。
我这个程序实际上是个组合C(n,r)的问题,其中参与组合的是一些字符串,对每一个新组成的字符串,判断其是否符合条件,如果符合,则保存;如果不符合,则不保存。主要的思路就是这样。
希望各位大富翁能帮我优化优化!
 
CombStr:=format('%s %s %s',[temp1,temp2,temp3]);
uball:=format('%s%s ',[uball,memo4.Lines.Strings[m]);
 
哈哈哈哈,我怎么一点就出来一个完成的提示啊,我把 n 设置到了 1000 ,一点还是立马
出来一个完成的提示,你,你,你,什么机器的干活?
 
for m:=0 to memo4.Lines.Count-1 do
if flag<8 then
if not AnsiContainsText(CombStr,memo4.Lines.Strings[m]) then
//memo4控件中的数据为标准数据,即memo4.Lines.Strings[m]与CombStr比较,如果不同,则保存
//memo4.Lines.Strings[m]数据,如下:uball:=uball+memo4.Lines.Strings[m]+' ';
begin
uball:=uball+memo4.Lines.Strings[m]+' ';
flag:=flag+1
//flag为记录保存数据的个数
end;

这段有点奇怪,为什么要限制8次?既然限制了,那么flag到8之后就可以跳出 m 循环了,这样可以加快很多
if flag<8 then ......
else break;

判断memo4.Lines.Strings[m]是否为CombStr的子串?你自己的说明有说是如果是判断是否相同,如果是判断相同就不该用函数,太慢
 
1.不要在循环中使用控件(包括TStrings)操作,它耗费的时间远远超出你的想象.可以使用数组.
2.不要使用Delphi自带函数,它要进行大量的数据类型判断和转换,太费时,自己写几个吧.
 
其实很简单的..只要把计算组合数的循环用组合数的优化公式就可以了...
 

Similar threads

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