如何使用BinarySearch
搜索数组中所有值的值? TArray.BinarySearch
中的默认System.Generics.Collections
仅返回一个索引。
示例数组:
A = [1,2,3,3,3,6,7,8,9];
答案 0 :(得分:3)
二进制搜索假定您已经对数组进行了排序,因此任何其他匹配元素将聚集在BinarySearch
返回的匹配元素周围。 Delphi XE5有助于注意
如果数组中有多个元素等于Item,则在FoundIndex中返回第一个匹配的索引。这是任何匹配项的索引,不一定是第一项。"
这表明您需要在数组中向前和向后运行搜索以获取所有匹配元素。
答案 1 :(得分:3)
让我向你解释一下这个问题。找到索引后,顺序搜索和二进制搜索之间的区别取决于您希望找到的数据类型。 10000个元素不相关,您要搜索的项目的值有多少。例如,如果我有一个由仅1,2,3,4和5组成的10000个元素的列表。我们讨论的情况是每个值可能有数千个,并且一系列随后的二进制搜索将更可取。如果值的范围可以从1到1000000,那么我们就不太可能有重复项,二进制搜索后跟两个方向的顺序搜索是最好的方法。
对于二进制和后续顺序方法,查找开始和结束索引的算法如下:
如果您想使用二进制搜索,那么您需要切换方法并进行一系列递归搜索,直到找到开始和结束。
代码示例看起来有点像这样。此代码用于在首次找到匹配项时退出的二进制搜索。
function GetIndexes(const aSearch: TSearchIntegers; const aValue: Integer; var aStartIndex, aEndIndex: Integer): Boolean;
var
foundIndex: Integer;
lookFor: Integer;
begin
if BinarySearch(aSearch, aValue, foundIndex) then
begin
Result := True;
lookFor := foundIndex;
repeat
aStartIndex := lookFor;
until not BinarySearch(aSearch, aValue, lookFor, TComparer<Integer>.Default, 1, aStartIndex - 1);
lookFor := foundIndex;
repeat
aEndIndex := lookFor;
until not BinarySearch(aSearch, aValue, lookFor, TComparer<Integer>.Default, aEndIndex + 1, High(aSearch) - aEndIndex);
end
else
Result := False;
end;
最终,您的数据(我们没有)将为您确定最佳行动方案。
现在让事情变得复杂一点。 Delphi在TArray.BinarySearch中使用的二进制搜索的变化是在找到匹配时不会提前结束的变化。它总是会找到第一个项目的索引,因为它在找到匹配项时不会退出循环。
Result := False;
L := Index;
H := Index + Count - 1;
while L <= H do
begin
mid := L + (H - L) shr 1;
cmp := Comparer.Compare(Values[mid], Item);
if cmp < 0 then
L := mid + 1
else
begin
H := mid - 1;
if cmp = 0 then
Result := True; // <-- It doesn't end here
end;
end;
这意味着当你有很多相同的值但你确实有一个很好的副作用时,你会有点惩罚。你可以做这样的事情来找到你想要的东西:
function GetIndexes(const aSearch: TSearchIntegers; const aValue: Integer; var aStartIndex, aEndIndex: Integer): Boolean;
begin
Result := False;
if TArray.BinarySearch<Integer>(aSearch, aValue, aStartIndex) then
begin
TArray.BinarySearch<Integer>(aSearch, aValue+1, aEndIndex);
if aSearch[aEndIndex] <> aValue then
Dec(aEndIndex);
Result := True;
end;
end;
这是有效的,因为即使数组中没有找到aValue + 1,搜索也会返回下一个值的索引。最后的if
语句用于处理我们的值也是数组的最后一个值的情况。
这取决于TArray.BinarySearch的代码保持原样。