c++ - 通过未排序的列表改进搜索

标签 c++ algorithm sorting search

我的代码将 40% 的时间用于搜索未排序的 vector 。更具体地说,搜索函数 my_search 重复接收长度为 N 的单个未排序 vector ,其中 N 可以取 10 到 100,000 之间的任何值。与每个元素关联的权重具有相对较小的方差(例如 [0.8, 0.81, 0.85, 0.78, 0.8, 0.7, 0.84, 0.82, ...])。

my_search 算法首先对每个对象的所有权重求和,然后对 N 元素(与 vector 的长度一样多)进行替换采样。该算法非常类似于

int sum_of_weight = 0;
for(int i=0; i<num_choices; i++) {
   sum_of_weight += choice_weight[i];
}
int rnd = random(sum_of_weight);
for(int i=0; i<num_choices; i++) {
  if(rnd < choice_weight[i])
    return i;
  rnd -= choice_weight[i];
}

来自 this post .

我可以在搜索之前对 vector 进行排序,但需要花费 O(N log N) 的时间(取决于使用的排序算法)并且我怀疑(但可能是错误的,因为我没有尝试过)我会获得很多时间,尤其是因为权重几乎没有差异。

另一种解决方案是存储一系列点之前有多少权重的信息。例如,在对 vector 求和时,每 N/10 个元素,我可以存储已求和了多少权重的信息。然后,我可以先将 rnd 与这 10 个断点进行比较,并只搜索 vector 总长度的十分之一。

  • 这是一个好的解决方案吗?
  • 我描述的过程有名称吗?
  • 如何根据 N 来估计要存储的断点的正确数量?
  • 有更好的解决方案吗?

最佳答案

log(N) 解决方案

{
    std::vector<double> sums;
    double sum_of_weight = 0;
    for(int i=0; i<num_choices; i++) {
       sum_of_weight += choice_weight[i];
       sums.push_back(sum_of_weight);
    }

    std::vector<double>::iterator high = std::upper_bound(sums.begin(), sums.end(), random(sum_of_weight));

    return std::distance(sums.begin(), high);
}

本质上与您有更好的解决方法的想法相同,但不是只存储十分之一的元素,而是存储所有元素并使用二进制搜索找到最接近您的值的索引。


分析

即使这个解决方案是 O(logN),您真的必须问问自己它是否值得。是否值得必须创建一个额外的 vector ,从而累积额外​​的时钟周期来将内容存储在 vector 中, vector 调整大小所需的时间,调用函数执行二进制搜索所需的时间等?

当我写上面的时候,我意识到你可以使用 deque 来代替,这几乎可以消除因必须调整大小和复制 vector 内容而不影响O(1) vector 查找。

所以我想问题仍然存在,将元素复制到另一个容器中然后只进行 O(logN) 搜索是否值得?

结论

TBH,我认为您从这次优化中获得的 yield 不多。事实上,我认为您获得了 O(logN) 的开销。

关于c++ - 通过未排序的列表改进搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40394199/

相关文章:

c++ - 使用cuda创建共现矩阵

c# - 在 C++ DLL 和 C# GUI 之间传递数据时结果不一致

java - 检查字符串是否包含字母表中的所有字母

c++ - 在排序的静态数组中搜索的最快方法

c++ - 模板类型未定义

c++ - 转换内联 C 汇编程序(Intel 语法到 AT&T)

javascript - 在排序的整数数组中查找范围的最大大小

c++ - 编译时拓扑排序超出 C++ 中的递归深度

javascript - 从 1970 年之前的日期数组中获取最高日期

c++ - 冒泡排序崩溃程序 C++