查找值落入哪个箱

Finding which bin a values fall into

本文关键字:查找      更新时间:2023-10-16

我试图找到双x属于哪个类别C。我的类别被定义为字符串名称,并在这样的文件中将值加倍

A 1.0
B 2.5
C 7.0 

应该这样解释

"A": 0 < x <= 1.0
"B": a < x <= 2.5
"C": b < x <= 7.0

(输入可以具有任意长度,并且可能必须按其值排序(。我只需要这样的函数

std::string findCategory(categories_t categories, double x) {
    ...insert magic here
}

所以对于这个例子,我希望

findCategory(categories, 0.5) == "A"
findCategory(categories, 1.9) == "B"
findCategory(categories, 6.0) == "C"

所以我的问题是 a( 如何编写函数和 b( category_t的最佳选择是什么(在 11 C++ 之前使用 stl(。我做了几次尝试,都是...不太成功。

一种选择是使用带有双精度作为键的 std::map 容器,以及与分配给其上限为给定值的范围的值相对应的值。 例如,给定您的文件,您将拥有如下所示的地图:

std::map<double, std::string> lookup;
lookup[1.0] = "A";
lookup[2.5] = "B";
lookup[7.0] = "C";

然后,您可以使用给定某个点的 std::map::lower_bound 函数来获取键/值对,其键(上端点(是映射中至少与相关点一样大的第一个键。 例如,使用上面的映射,lookup.lower_bound(1.37)将返回值为"B"的迭代器。 lookup.lower_bound(2.56)将返回值为"C"的迭代器。 这些查找速度很快;对于具有 n 个元素的映射,它们需要 O(log n( 时间。

在上面,我假设您查找的值都是非负值。 如果允许负值,则可以添加快速测试,以在执行任何查找之前检查该值是否为负值。 这样,您可以消除虚假结果。

值得一提的是,如果您碰巧知道查找的分布(例如,它们是均匀分布的(,则可以构建一种称为最佳二叉搜索树的特殊数据结构,该结构将提供比std::map更好的访问时间。 此外,根据您的应用,可能会有更快的选项可用。 例如,如果你这样做是因为你想随机选择一个具有不同概率的结果,那么我建议你研究这篇关于别名方法的文章,它允许你在 O(1( 时间内生成随机值。

希望这有帮助!

您可以使用配对类型和算法中的"lower_bound"<>http://www.cplusplus.com/reference/algorithm/lower_bound/。

让我们根据上边缘定义您的类别: Typedef 对 categories_t;

然后只需制作这些边缘的向量并使用二叉搜索进行搜索。请参阅下面的完整示例。

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
typedef pair<double,string> category_t;
std::string findCategory(const vector<category_t> &categories, double x) {
   vector<category_t>::const_iterator it=std::lower_bound(categories.begin(), categories.end(),category_t(x,""));
   if(it==categories.end()){
      return "";
   }
   return it->second;
}
int main (){
   vector< category_t > edges;
   edges.push_back(category_t(0,"bin n with upper edge at 0 (underflow)"));
   edges.push_back(category_t(1,"bin A with upper edge at 1"));
   edges.push_back(category_t(2.5,"bin B with upper edge at 2.5"));
   edges.push_back(category_t(7,"bin C with upper edge at 7"));
   edges.push_back(category_t(8,"bin D with upper edge at 8"));
   edges.push_back(category_t(9,"bin E with upper edge at 9"));
   edges.push_back(category_t(10,"bin F with upper edge at 10"));
   vector< double > examples ;
   examples.push_back(1);
   examples.push_back(3.3);
   examples.push_back(7.4);
   examples.push_back(-5);
   examples.push_back(15);
   for( vector< double >::const_iterator eit =examples.begin();eit!=examples.end();++eit)
      cout << "value "<< *eit << " : " << findCategory(edges,*eit) << endl;   
}
比较

按照我们想要的方式工作,因为双精度是货币对中的第一个,并且首先通过比较第一个成分来比较配对,然后比较第二个成分。否则,我们将定义一个比较谓词,如我上面链接的页面中所述。