给段代码参考,采用2分法,但一次只能找出第一个不连续的数,但速度很快,特别是数量非常大时且非连续数少时效率很高,循环次数是 len(count)+2,数量小时没优势,要连续找,可以循环调用,改变base值即可,这是一个基于数据表的,改改就可以基于数组之类了
procedure TBSelectIDByBase(ADataSet:TADODataSet;AID:string;Base:integer;
var RID:integer);
{ 找出表 ADataSet中字段AID非连续的值以Base 为基 如:若从"0"开始,则
Base 为-1 }
procedure TBSelectIDByBase(ADataSet:TADODataSet;AID:string;Base:integer;var RID:integer);
var
i,j,k:integer;
StSort:string;
begin
k:=1;
ADataSet.DisableControls;
StSort:=ADataSet.Sort;
ADataSet.Sort:=AID+' ASC';
try
i:=ADataSet.RecordCount;
if i=0 then
begin
RID:=base+1;
exit;
end;
ADataSet.Last;
if i=ADataSet.FieldByName(AID).AsInteger-base then RID:=i+base+1
else
if i=0 then RID:=base+1
else
begin
j:=i div 2;
ADataSet.First;
while (j>1)or(j<-1) do
begin
ADataSet.MoveBy(j);
if k+j>i then k:=i
else if k+j<1 then k:=1
else k:=k+j;
if k=ADataSet.FieldByName(AID).AsInteger-base then
j:=abs((j div 2)+(j mod 2))
else j:=-abs((j div 2)+(j mod 2));
end; // while (j>1)or(j<-1)
case j of
-1:begin
while (k<>ADataSet.FieldByName(AID).AsInteger-base)and(k<>1) do
begin
ADataSet.Prior;
dec(k);
end;
if k=ADataSet.FieldByName(AID).AsInteger-base then RID:=k+1+base
else RID:=base+1;
end;{end -1}
1:begin
while (k=ADataSet.FieldByName(AID).AsInteger-base)and(k<>i) do
begin
ADataSet.Next;
inc(k);
end;
if k<>ADataSet.FieldByName(AID).AsInteger-base then RID:=k+base
else RID:=i+1+base;
end;{end 1}
0:if ADataSet.FieldByName(AID).AsInteger=1+base then RID:=2+base
else RID:=1+base;
end;{end case}
end;
finally
ADataSet.Sort:=StSort;
ADataSet.EnableControls;
end;
end;