Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 寻找一个高效的数据结构来进行快速搜索_C++_C_Algorithm - Fatal编程技术网

C++ 寻找一个高效的数据结构来进行快速搜索

C++ 寻找一个高效的数据结构来进行快速搜索,c++,c,algorithm,C++,C,Algorithm,我有一个大约1000个元素的列表。包含4个变量的每个元素(我从文件中读取的对象,因此我可以在开始时有效地排列它们)。所以现在我在做以下事情,这在大计划中是非常低效的: void func(double value1, double value2, double value3) { fooArr[1000]; for(int i=0;i<1000; ++i) { //they are all numeric

我有一个大约1000个元素的列表。包含4个变量的每个元素(我从文件中读取的对象,因此我可以在开始时有效地排列它们)。所以现在我在做以下事情,这在大计划中是非常低效的:

void func(double value1, double value2, double value3)
{

       fooArr[1000];

       for(int i=0;i<1000; ++i) 
       {
                   //they are all numeric! ranges are < 1000
                  if(fooArr[i].a== value1
                       && fooArr[i].b >= value2;
                       && fooArr[i].c <= value2; //yes again value2  
                       && fooArr[i].d <= value3; 
                   )
                   {
                            /* yay found now do something!*/
                    }
       } 
}
void func(双值1、双值2、双值3)
{
fooArr[1000];
对于(int i=0;i=value2;

&&fooArr[i].c如果空间不是太重要,那么最简单的方法就是根据“a”上的冲突数量创建一个基于“a”的哈希表。让哈希表中的每个节点都指向一个基于“b”的二叉树可能是有意义的。如果b有很多冲突,那么对c也一样


第一个索引到散列中,这取决于有多少冲突,将为您节省大量时间,只需很少的编码或数据结构工作。

如果空间不是太重要,最简单的方法是根据“a”创建一个基于“a”的散列,这取决于您在“a”上得到的冲突数量让哈希表中的每个节点都指向一个基于“b”的二叉树可能是有意义的。如果b有很多冲突,那么对c也一样


第一个索引到散列中,取决于有多少冲突,这将为您节省大量时间,只需很少的编码或数据结构即可工作。

看,这只是一个线性搜索。如果您可以做一个更好的搜索,那会很好,但您复杂的匹配要求让我不清楚是否有可能,比如,保持排序并使用二进制搜索

话虽如此,也许有一种可能性是生成一些索引。主索引可能是键入
a
属性的字典,将其与该属性具有相同值的元素列表相关联。假设该属性的值分布均匀,它将立即消除绝大多数索引比较


如果属性值有限,则可以考虑添加一个附加的索引,该项通过“代码> B <代码>排序,甚至可能是按代码< C>代码>排序的另一个索引(但按相反的顺序排序)。.

看,这只是一个线性搜索。如果你能做一个更好的搜索,那就太好了,但是你复杂的匹配要求让我不清楚是否有可能,比如说,保持排序并使用二进制搜索

话虽如此,也许有一种可能性是生成一些索引。主索引可能是键入
a
属性的字典,将其与该属性具有相同值的元素列表相关联。假设该属性的值分布均匀,它将立即消除绝大多数索引比较


如果属性值有限,则可以考虑添加一个附加的索引,该项通过“代码> B <代码>排序,甚至可能是按代码< C>代码>排序的另一个索引(但按相反的顺序排序)。.

由于您只有三个要匹配的属性,因此可以使用哈希表。在执行搜索时,您使用哈希表(它为a属性编制索引)要查找a与某个常量匹配的所有条目,请检查b和c是否与常量匹配。这样可以减少比较次数。我认为这将大大加快搜索速度


除此之外,您还可以构建三个二进制搜索树。其中一个按每个属性排序。搜索完所有三个树后,您可以对每个树中与您的值匹配的树执行操作。

因为您只有三个属性要匹配,所以可以使用哈希表。执行搜索时,您可以使用哈希表(对a属性进行索引)以查找a与
SomeConstant
匹配的所有条目。然后检查b和c是否也与常量匹配。这样可以减少比较次数。我认为这将大大加快搜索速度


除此之外,您还可以构建三个二进制搜索树。其中一个按每个属性排序。在搜索完所有三个树后,您可以对每个树中与您的值匹配的树执行操作。

如果您的应用程序已经在使用数据库,则只需将它们放在一个表中并使用查询来查找。我在一些应用程序中使用mysql,并将重新编译结束它。

如果你的应用程序已经在使用数据库,那么就把它们放在一个表中,然后使用查询来查找它。我在我的一些应用程序中使用mysql,我会推荐它。

首先,按增加a和减少b对列表进行排序。然后在a上建立一个索引(值是从0到999的整数。因此,我们得到了

int a_index[1001];  // contains starting subscript for each value
a_index[1000] = 1000;

for (i = a_index[value1]; i < a_index[value1 + 1] && fooArr[i].b >= value2; ++i)
{
   if (fooArr[i].c <= value2 && fooArr[i].d <= value3) /* do stuff */
}
int a_index[1001];//包含每个值的起始下标
a_指数[1000]=1000;
对于(i=a_索引[value1];i=value2;++i)
{

如果(fooArr[i].c首先,对增加a和减少b的列表进行排序。然后在a上建立索引(值是从0到999的整数。因此,我们得到

int a_index[1001];  // contains starting subscript for each value
a_index[1000] = 1000;

for (i = a_index[value1]; i < a_index[value1 + 1] && fooArr[i].b >= value2; ++i)
{
   if (fooArr[i].c <= value2 && fooArr[i].d <= value3) /* do stuff */
}
int a_index[1001];//包含每个值的起始下标
a_指数[1000]=1000;
对于(i=a_索引[value1];i=value2;++i)
{

如果(fooArr[i].c您可以使用标准模板库(STL)中的hash_集,这将为您提供非常高效的实现。搜索的复杂性将是O(1)

以下是链接:

--编辑--

声明新结构,该结构将保存变量,重载比较运算符并生成此新结构的哈希集。每次要搜索时,使用变量创建新对象并将其传递给哈希集方法“find”

似乎哈希_集对于STL不是必需的,因此您可以使用set,它将为您的搜索提供O(LogN)复杂度。 下面是一个例子:

#include <cstdlib>
#include <iostream>
#include <set>

using namespace std;

struct Obj{

public:
       Obj(double a, double b, double c, double d){
                this->a = a;
                this->b = b;
                this->c = c;
                this->d = d;
       }

       double a;
       double b;
       double c;
       double d;
       friend bool operator < ( const Obj &l, const Obj &r )  {
              if(l.a != r.a)  return l.a < r.a;
              if(l.b != r.b) return l.a < r.b;
              if(l.c != r.c) return l.c < r.c;
              if(l.d != r.d) return l.d < r.d;
              return false;

       }
  };


 int main(int argc, char *argv[])
{
set<Obj> A;

A.insert( Obj(1,2,3,4));
A.insert( Obj(16,23,36,47));
A.insert(Obj(15,25,35,43));

Obj c(1,2,3,4);

A.find(c);
cout <<    A.count(c);



system("PAUSE");
return EXIT_SUCCESS;
}
#包括
#包括
#包括
使用名称空间std;
结构对象{
公众:
Obj(双a、双b、双c、双d){
这->a=a;
这->b=b;
这个->c=c;
std::vector<foo *> const &values = index[value1];
for (int i=0; i<values.size(); i++) {
    if (value2 <= values[i]->b
        && value2 >= values[i]->c
        && value3 >= values[i]->d) {
            // yay, found something
        }
}
b = 96  46  47  27  40  82   9  67   1  15
c = 76  23  91  18  24  20  15  43  17  10
d = 44  30  61  33  21  52  36  70  98  16
idx[a].bc[50] = 0000010100
idx[a].d[50]  = 1101101001
idx[a].bc[20] = 0001010000
idx[a].d[20]  = 0000000001
g = idx[a].bc[20] & idx[a].d[50];
tg = g
n = 0
while (tg > 0){
  if(tg & 1){
    // do your stuff
  }
  tg = tg >>> 1;
  n++;
}
std::vector<Bucket1> myTable(1001, /*MAGIC_1*/); // suspense
 && fooArr[i].b >= value2
 && fooArr[i].c <= value2 //yes again value2
 && fooArr[i].d <= value3
 typedef std::vector<Bucket2> Bucket1;
 /*MAGIC_1*/ <-- Bucket1(1001, /*MAGIC_2*/) // suspense ?
 typedef std::vector< std::vector<YourObject*> > Bucket2;
 /*MAGIC_2*/ <-- Bucket2(1001)
class Collection:
{
public:
  Collection(size_t aMaxValue, size_t bMaxValue, size_t dMaxValue);
    // prefer to use unsigned type for unsigned values

  void Add(const YourObject& i);

  // Pred is a unary operator taking a YourObject& and returning void
  template <class Pred>
  void Apply(int value1, int value2, int value3, Pred pred);

  // Pred is a unary operator taking a const YourObject& and returning void
  template <class Pred>
  void Apply(int value1, int value2, int value3, Pred pred) const;

private:
  // List behaves nicely with removal,
  // if you don't plan to remove, use a vector
  // and store the position within the vector
  // (NOT an iterator because of reallocations)
  typedef std::list<YourObject> value_list;

  typedef std::vector<value_list::iterator> iterator_vector;
  typedef std::vector<iterator_vector> bc_buckets;
  typedef std::vector<bc_buckets> a_buckets;
  typedef std::vector<a_buckets> buckets_t;

  value_list m_values;
  buckets_t m_buckets;
}; // class Collection

Collection::Collection(size_t aMaxValue, size_t bMaxValue, size_t dMaxValue) :
  m_values(),
  m_buckets(aMaxValue+1,
            a_buckets(bMaxValue+1, bc_buckets(dMaxValue+1))
           )
  )
{
}

void Collection::Add(const YourObject& object)
{
  value_list::iterator iter = m_values.insert(m_values.end(), object);

  a_buckets& a_bucket = m_buckets[object.a];
  for (int i = object.c; i <= object.b; ++i)
  {
    bc_buckets& bc_bucket = a_bucket[i];
    for (int j = 0; j <= object.d; ++j)
    {
      bc_bucket[j].push_back(index);
    }
  }
} // Collection::Add

template <class Pred>
void Collection::Apply(int value1, int value2, int value3, Pred pred)
{
  index_vector const& indexes = m_buckets[value1][value2][value3];
  BOOST_FOREACH(value_list::iterator it, indexes)
  {
    pred(*it);
  }
} // Collection::Apply<Pred>

template <class Pred>
void Collection::Apply(int value1, int value2, int value3, Pred pred) const
{
  index_vector const& indexes = m_buckets[value1][value2][value3];

  // Promotion from value_list::iterator to value_list::const_iterator is ok
  // The reverse is not, which is why we keep iterators
  BOOST_FOREACH(value_list::const_iterator it, indexes)
  {
    pred(*it);
  }
} // Collection::Apply<Pred>