我想知道是否有人知道在 C# 的非常密集的搜索(在数组中)(我指的是数百万个元素的数组)中,哪种方法最高效,例如最好使用 IndexOf 或 BinarySearch 来获得元素的索引?我应该使用数组还是 HashSet?以及如何使用 HashSet 在数组中查找匹配项?
我需要的算法的一个逻辑示例:
块:071827490593720123213023498230402000813
查找值:40200
目标:返回所述数字组所在的索引
应该返回什么:30
我目前实现的代码:
int offSet = 0;
while ((offSet = Array.IndexOf(bloque, encontrar[0], offSet)) != -1)
{
if (encontrar.Length > 1)
for (int i = 1; i < encontrar.Length; i++)
{
if (bloque.Length <= offSet + encontrar.Length) break;
else if (encontrar[i] != bloque[offSet + i])
{
if (bloque[offSet + i] == encontrar[0])
{ offSet += (i - 1); break; }
else if (i == encontrar.Length - 1)
{ offSet += i; break; }
break;
}
else if (i == encontrar.Length - 1)
addresses.Add(new IntPtr((int)baseAddress + offSet));
}
else addresses.Add(new IntPtr((int)baseAddress + offSet));
offSet++;
}
这个算法并不慢,但它不像我正在比较的程序那样快速搜索。我正在开发的程序打开进程并在其内存区域中查找值(是的,我正在将其与 Cheat Engine 进行比较)。如您所见,它或多或少类似于 Boyer Moore 的算法,但我需要知道是否可以替换函数以提高性能,或者是否应该删除或更改算法逻辑中的某些内容以提高性能。
https://es.wikipedia.org/wiki/Algorithm_of_b%C3%BAsqueda_de_cadenas_Boyer-Moore
首先,我会分析执行情况,看看它们是否告诉我有关代码行为的任何信息。
我会尝试的事情,因为我理解的这些事情比其他任何事情都更加反复试验。也许在这个时候你已经做了:
encontrar
为 1 的情况(我们得到一个if
from 循环。while
可以消除offSet += (i - 1)
仅使用break
addresses.Add(new IntPtr((int)baseAddress + offSet))
. 实例化和添加到集合中,相对于循环执行而言可能代价高昂。更新
Rational:您正在执行转换,创建一个 IntPtr 对象并将其添加到地址。与算法的其余部分相比,特别是第二个操作可能会很昂贵,毕竟创建对象不是免费的(这是您应该测试的假设)。
可以做些什么呢?好吧,您可以尝试将该任务委托给另一个进程或线程。
也就是说,构建一个生产者/消费者方案,其中生产者(您当前的进程)将 baseAddress+offset 传递给消费者,消费者创建 IntPtr 并将其添加到其集合中。
然后在执行完成时,您可以要求创建 IntPtr 的使用者返回生成的 IntPtr 集合。
这个想法是,在多处理器环境中,搜索过程和创建过程落在不同的处理器上,这样您可以获得更高的性能。
这里有一篇关于它的文章。
结局
当然,我可能对所有事情都错了。以响应形式阅读您的结果可能会更有趣。
您没有评估使用
Regular Expression
来获取块有了这个,您可以搜索所有匹配项
资料来源: 是否有一个函数可以返回 RegEx 匹配开始的索引?