说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

算法问题!!要求在5~20分钟内完成全部循环

编辑:说三道四文库 发布时间:2018-05-22 04:07
HTML文档下载 WORD文档下载 PDF文档下载
listbox1中有300000条数据长度是15,另一个listbox2中有1000条记录,长度为15
要求在5~25分钟内把listbox1中的每条数据与listbox2中的每条数据对比,看看对应位置的字符是否相同,有几个相同!,算法我已经作出来了,不过速度慢,请大家帮忙看看。
我循环里的数据量可能是300000×15×1000=4500000000(单个字符进行比较)
排序完毕,作折半查找。这个最有用了。
详细说一下,将两个ListBox里面TStrings转换为TStringList,

然后Sort排序一下,把你的顺序搜索改为,折半搜索。

建议:最好不用Sort,用CustomSort,你的排序和查找的比较函数最好一致。
如果稍复杂,建立一个二叉查找数来比较。

看你的数据,应该是用少的往多的比较。

我不明白的是,你为什么用ListBox存储,本身就很低效了。不明白……
...
listbox1.indexof(listbox2.items[i])=-1 ;//no exist
...
我问问楼上的,我从来没有见过listbox1.indexof,你从哪里找来的????

function TStrings.IndexOf(const S: string): Integer;
begin
  for Result := 0 to GetCount - 1 do
    if CompareStrings(Get(Result), S) = 0 then Exit;
  Result := -1;
end;

我还要找出对应相同的个数:
比如
j:integer;
for i:=1 to 15 do
if aString[i]=s[i] then
j:=j+1;
listbox是显示的
只对比里面的数据
这个倒是次要的,

关键是如何高效的将两个数据源遍历。
你的DoubleBuffered有没有开?
我很不明白,用ListBox显示300K的数据。如果是我,

我宁愿用RichText,或者Memo都比它强……

把你的算法和数据发一份给我,要不然什么都做不了。

要不你把你的算法贴出来。
注意,我要比较每条记录中相同字符的个数:
比如:
listbox1:        listbox2
123456852345895  121456654123565
要比较listbox1中的记录的第一个字符和listbox2中的第一个字符
listbox1中的记录的第二个字符和listbox2中的第二个字符
listbox1中的记录的第三个字符和listbox2中的第三个字符
...
假如第一个相同:   j=1
第二个相同        j:=2
3~5没有相同的
第六个相同     j:=3
...
要listbox1中的第一条记录分别和listbox2中的所有记录进行比较
按照你的要求似乎没什么高效的办法,干脆用汇编写吧。
程序:
        for j:= 0 to listbox1.Count-1 do
        for i:=0 to 1000 do
        begin
for k:=1 to 13 do  
         begin             
                        if aString[k]=Posstring[k] then
                        begin
                                j:=j+1;
                        end;
         end
        end;
aString:当前listbox1中的数据 Posstring:当前listbox2中的数据
我是单个字符进行比较
唉,建议你把这些数据保存成文本,然后用内部搜索比较好。

看了你的解释明白了,你所有的数据都要互相比较。

从比较次数上无法改善了,

最好的办法就是用空间换时间了。。。。。。
不要把数据放在ListBox中,放在内存中.可以加快取出数据的速度.
把内存中的字串当作数值处理,内嵌汇编进行循环和比较
pankun:汇编现在很长时间没用了,只在大学的时候用过
高分求教,觉得分不够,再加200
如果把300000条数据放在内存里,是不是太大了
看不大明白你說的
>>注意,我要比较每条记录中相同字符的个数:
>>比如:

但我比較排序很重要, 先記錄, 去掉重復的記錄, 
然後 , 如果
ListBox1 第一條 match listbox2 第三條記錄, 

listbox1 第二條 應該直接與 listbox2 的第四條 match 了!

象字符串查找的算法的原理也差不多!


第一反應是這樣做, 有什麼好想法, 再討論!
建议:

一、对两组数据进行排序,这样可以有效的筛选访问效率高。

二、用指针访问会比下标访问快一点点,不过可能积少成多,会有效一些。

不知道你用得是不是纯数字。纯数字可能快一些。
倒入到数据库中,一条SQL语句就搞定了
数据中有别的字符,比如','
看来你是不知道内存的作用和厉害程度。

你的数据才300K*15 = 4M而已,

我的是20M,都放到内存,而且加了索引才17兆内存。

如果你想快,就得用空间换时间。
>>如果把300000条数据放在内存里,是不是太大了
感覺是太大了!

然後, 考慮另一種, 放到數據庫, 加索引, 
用SQL查詢優化出來的的效果, 又不知如何??
aiirii(ari-爱的眼睛):
但我比較排序很重要, 先記錄, 去掉重復的記錄, 
然後 , 如果
ListBox1 第一條 match listbox2 第三條記錄, 

listbox1 第二條 應該直接與 listbox2 的第四條 match 了!

象字符串查找的算法的原理也差不多!


///////////////////////////////////////////////
ListBox1 第一條 match “listbox2 第三條記錄,”(listbox2所有的记录) 

listbox1 第二條 應該直接與 ”listbox2 的第四條 match 了!“(listbox2所有的记录)
看看能否从需求上做到简化!

如pankun所说门把数据读入到内存的数组里面,直接用混编写效率会高些。
另外感觉你使用 P4的SSE 应该有些优势,他是128bit的,虽然浮点才是她的强项。
很抱歉:不要求用数据库。
你把你的数据存成文本给我压缩发一份给我。

用ListBox1.Lines.SaveToFile
ListBox2.Lines.SaveToFile

real-like#163.com

把#换成@,防止那些垃圾邮件收集邮件列表。
放在数据库管理方便,但是效率肯定比直接奥佐内存要低得多。

我原来做的一个防伪系统,采用20位编码,常常由用户因为编码模糊,会有1,2位看不清,需要核对。
随意我需要从数据库中匹配。

数据总量大约2亿。
我的匹配任务就是这2亿数据中找到和他只差2位编码的记录,复杂度和你有一拼吧?
这么大的数据量用数据库存放呀,然后用sql语句查询。
我就不信!300000条数据在数据库是什么感觉。

我就不信,我从来都保留5000条数据,如果超出这个我就cut。

给我找个数据库,能够遍历300000数据很快!
pazee(耙子)(灵感点亮生活) 
恩,差不多,你怎么做的?(如果不放入数据库的话)
数据量越大越用文本做数据存储。。。。。。
2亿里面匹配一次至少需要几个小时。

通过修改需求,优化算法如下。
1、首先我们根据不同产品,可以直接筛选出2亿里面的大约几十分之一的;
2、把20位编码分成4组,每组5个码,放入4列,分别建立索引,(所以建了整整一天才完成)
3、假定每个编码中4组中至少有一组完全正确(因为实际工作中条件一定满足)

匹配的时候把需要匹配的编码认为分成4组,然后以每组为索引分别匹配,

这样复杂度就变成了 logn/log2 了
之后匹配一次的速度只有不到一分钟。

你感觉和你的有类似不?
多开几个线程,把listbox1的数据分面若干段,每段数据放在一个线程里面和listbox2比较,时间应该会短些
reallike(学习SICP还有Lisp……) :
if  ODialog.Execute then
     begin
        AssignFile(txtFile,ODialog.FileName);
        Reset(txtFile);
        while not Eof(txtFile) do
        begin
            判断???
        end;
你随便制定一个文件名,比如1.txt,就会保存到exe所在目录

你指定绝对路径也行,C:\1.txt,就会直接保存到那里。

ListBox1.Items.SaveToFile('1.txt');

唉……上面写错了。。。。。。写成了Line,不常用ListBox
你把你的数据存成文本给我压缩发一份给我。

用ListBox1.Lines.SaveToFile
ListBox2.Lines.SaveToFile

real-like#163.com

把#换成@,防止那些垃圾邮件收集邮件列表。

-------------------------------------------

我也要, akunspy#sina.com
回复人: lemon_wei(soft_fans) ( ) 信誉:99  2004-06-15 13:22:00  得分: 0  
 
 
   多开几个线程,把listbox1的数据分面若干段,每段数据放在一个线程里面和listbox2比较,时间应该会短些

-------------------------------------------------------------------------------
呵呵,老兄,CPU可不能并发处理线程.我想这样也不能提高速度吧
我的思路和aiirii得有些相同,你没有理解,

首先要排序,其次要找到完全相同的那些。
分析如下
  每个位置上的字符只可能是 2^16个(按unincode编码)
  没有必要将listbox1的300000 与listbox2 的1000 记录逐条比较
  先统计出listbox1和listbox2中个各字符的个数 形成两个数组
  这样需比较的记录的条数最多也就2^16个
  这样操作15次
  这样最复杂的情况下比较和遍历的次数是
  (300000 + 1000 )* 2^16 * 2 *15
楼上的没看清题,呵呵.

要求的是对应位置的字符相比较.而不是相同的字符就行.
楼上的你得比较次数:591790080000

我很佩服你搞复杂了。。。。。
hehe^^ 要说算法...我没有想到有什么好的,不过第一感觉就是如楼上所说的,以空间换时间...这算是个笨办法了
先将
另一个listbox2中有1000条记录,长度为15
预处理 成 一个 26 * 15 行字符的对应表,列记载对应的位置,

然后用个 for 循环

listbox1中有300000 的每个字符对应查表,如何??
个人觉得aiirii(ari-爱的眼睛) 的方法好一点
已经发送给两位邮件了,请查收
哦,看了你的数据原本,我明白一些了。

不过我不明白的事,到底是找不同还是找相同?

你们是不是要做差错分析?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘