关于tstringlist的算法 请各位大富翁帮帮忙 ( 积分: 100 )

  • 主题发起人 主题发起人 MaXsl
  • 开始时间 开始时间
M

MaXsl

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在2个TStringList已经排序好
比如:1
/ww/123.exe
/ww/as.c
/ww/az.cc
/ww/sd.x
2
/ww/aaa.exe
/ww/sas.exe
/ww/sd.x

可能实际情况要多得多 可能几万个 我就想找到一种算法能够只遍历一次就能把2中没有的和1中没有的找出来
 
把两个TStringList的内容都放到一个TStringList(A)中
然后在A中遍历1和2的成员,有两个的话,说明两个中都有,有一个的话说明存一个集合中.
 
就是两个集合的差异吗,还是多遍,即使排序(实际上就是遍历了)
 
分别放到一个文本文件中
然后ADO连接,数据库查询
 
能给出具体的代码吗? 有没有更优一点的算法啊 。 期待高人
hzjzxp兄给出了一个思路
to bsense:是的 就是要求出差异
to boy2002cn:我的程序没有用到数据库
 
如有一个方法,可只遍历2个TStringList各一遍即可实现楼主的要求,为叙述方便,以下称2个TStringList分别为 LA和LB。(前提要同楼主讲得一样,LA与LB要已排序的哦,否则不能用),下面给出算法伪代码

VAR TPA,TPB: TStringList
分别用来保存 LA、LB不存在的元素
TPPUB:TStringList
保存LA、LB相同的元素

While (LA.Count > 0) And (LA.Count > 0) do begin
if LA.Strings[0] = LB.Strings[0] then
begin
LA.Strings[0] -> tpPUB

LA.Items[0].delete;
LB.Items[0].delete;
Continue;
End;
While LA.Strings[0] > LB.Strings[0] do
begin
LB.Strings[0] -> tpLB;
LB.Items[0].delete;
if LB.Count = 0 then
Break;
end;
While LB.Strings[0] > LA.Strings[0] do
begin
LA.Strings[0] -> tpLA;
LA.Items[0].delete;
if LA.Count = 0 then
Break;
end;
end;
if LA.Count > 0 then
TPA.AddStrings[LA]
if LB.Count > 0 then
TPB.AddStrings[LB]
说明:
算法即通过比较LA、LB的头元素是否相同,如果相同,则保存到公共变量中,并将两个序列的相同元素删除,然后比较接下来的头元素,如果LA的>LB的,两者之间不可能匹配,至少要把LB的位置推进到<=的位置,才有可能再次匹配,反之也相同。
最后,除非LA与LB最后一个元素相同,否则无论哪个元素已为0,另一个余下的,肯定都是找不到匹配的,故要添加到差异集合中。

怎么样?以上算法是不是AB均只遍历了一遍?
 
to levi:如果A与B都遍历一次的话 就简单了啊
但是我需要的是只遍历一次就出结果啊
 
帮帮忙啊 顶起来
 
只遍历一次!
(要求代码简洁,还是执行效率高?)
你看这个算法如何:
for i:=list1.count-1 downto 0 do begin
j:=list2.indexof(list1.strings);
if j>=0 then begin
list1.delete(i);
list2.delete(j);
end
end;
这样,list1中剩下的,list2中肯定没有;list2中剩下的,list1中肯定没有。
不知道是不是这个意思。
 
To: MaXsl
要跟别人比较,又要一次也不遍历对方? 你厉害,如果有这种算法,请你也告诉我一下。
确切的可以说,理论如果还能有遍历次数少于 LA.Count + LA.Count 的算法,那就奇怪了。

To: yeskert1
表面上看,你的算法是只遍历了一次List1,但是可知道 indexof 函数也会遍历一次LIST2,所以这个算法的效率实际上是 List1.Count * List2.Count
function TStringList.IndexOf(const S: string): Integer;
begin
if not Sorted then Result := inherited IndexOf(S) else
if not Find(S, Result) then Result := -1;
end;

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;

function TStringList.Find(const S: string
var Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := FCount - 1;
while L <= H do
begin
I := (L + H) shr 1;
C := CompareStrings(FList^.FString, S);
if C < 0 then L := I + 1 else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
if Duplicates <> dupAccept then L := I;
end;
end;
end;
Index := L;
end;
 
恩 今天中午我也想明白了这个问题
最优的算法也至少是m+n就算是用hzjzxp的方法 表面上看来好像只遍历其中的一个stringlist 其实另一次遍历也悄悄做了不过是stringlist自己做的
再次感谢levi的指点
谢谢大家对此问题的关注 (^-^)[:)]
 
多人接受答案了。
 
[:D]
我当然知道!
 
后退
顶部