Time 建议一种查找时间复杂度最低的好方法

Time 建议一种查找时间复杂度最低的好方法,time,complexity-theory,lookup,data-structures,Time,Complexity Theory,Lookup,Data Structures,我有一个结构,它有3个标识符字段和一个值字段。我有这些物品的清单。打个比方,标识符字段类似于对象的主键。这三个字段唯一标识一个对象 Class { int a1; int a2; int a3; int value; }; 我会有一个列表,比如说1000个这个数据类型的对象。我需要通过将a1、a2和a3的值传递给查找函数来检查这些标识键值的特定值,该函数将检查是否存在具有这些特定值a1、a2和a3的任何对象并返回该值。实现此功能以获得最佳查找时间的最有效方法是什么 我能

我有一个结构,它有3个标识符字段和一个值字段。我有这些物品的清单。打个比方,标识符字段类似于对象的主键。这三个字段唯一标识一个对象

Class
{
   int a1;
   int a2;
   int a3;
   int value;
};
我会有一个列表,比如说1000个这个数据类型的对象。我需要通过将a1、a2和a3的值传递给查找函数来检查这些标识键值的特定值,该函数将检查是否存在具有这些特定值a1、a2和a3的任何对象并返回该值。实现此功能以获得最佳查找时间的最有效方法是什么

我能想到的一个解决方案是用一个长度为1000的三维矩阵来填充其中的值。这具有O(1)的查找时间。但缺点是。 1.我需要知道数组的长度。 2.对于更高的标识字段(比如20),那么我需要一个20维矩阵,这对内存来说是一个过度消耗。对于我的实际实现,我有23个标识字段


您能推荐一种存储此数据的好方法,以提供最佳的查找时间吗?

创建一个包含所有标识字段的密钥类,并定义适当的equals函数和哈希方法,然后使用哈希映射将密钥类映射到其关联值。在预期情况下,每次查找的时间复杂度为O(1),并且只需要与实际观察到的键组合数成比例的空间(通常是该数字的两倍,尽管您可以根据所需的时间/空间权衡调整该常数),而不是与所有可能的键组合成比例的空间。

使用哈希表(map)。将键构造为“a1-a2-a3”,并将数据存储到H(键)=数据。

我只需按键对数组排序,并使用二进制搜索

(未经测试)

int比较_条目(条目*k1,条目*k2){
INTD=k1->a1-k2->a1;
如果(d==0){
d=k1->a2-k2->a2;
如果(d==0){
d=k1->a3-k2->a3;
}
}

返回d;//>0是k1>k2,如果k1==k2,则返回0,a1、a2和a3的范围值是多少?如果n=1000确实是列表的大小,则线性搜索不会很困难。如果n显著大于1k,则将键串联起来并将值存储在(散列(键),值)中映射。在我的实际实现中,我有a1,a2…a23。请记住,如果您有一个完美的散列(每个桶一个项目),那么n可能是10-20K。这通常需要预先了解密钥属性。@paxdiablo,它仍然是O(1),即使没有一个完美的散列函数……相信与否,即使使用普通的散列表实现,也会发生冲突……如果您使用boost::hash_combine之类的东西来构造散列函数,那么生成一个分布均匀的散列函数应该不会有问题。它不是O(1).Perfect hash,根据定义,将每个值映射到一个唯一的键。这将是O(1),因为无论数据集大小如何,操作数都是相同的。在任何哈希不完美的实现中,它都是O(n)对于每个bucket中的简单列表,虽然如果每个bucket是另一个hash,则可以将其优化为更少。但它永远不会达到神秘的O(1)。恐怕我们不得不同意不同意。这与说您已将所有内容存储在未排序的列表中,并说您受到1000个数组元素比较的限制没有什么不同,因此是常数时间。事实上,复杂性取决于,而不是1(常数时间),但取决于元素的数量。当n接近无穷大(或任意大的数)时,除数与复杂性分析无关,它仍然依赖于n。@paxdiablo,我相信您混淆了最坏情况性能和平均情况性能。虽然最坏情况性能确实是O(n)--假设所有散列都碰撞到同一个索引--在预期情况下为O(1)。
int compare_entry(ENTRY *k1, ENTRY *k2) {    
    int d = k1->a1 - k2->a1;
    if (d == 0) {
        d = k1->a2 - k2->a2;
        if (d == 0) {
            d = k1->a3 - k2->a3;
        }
    }
    return d; // >0 is k1 > k2, 0 if k1 == k2, <0 if k1 < k2
}

// Derived from Wikipedia
int find(ENTRY *list, int size, ENTRY *value) {
   int low = 0;
   int n = size - 1;
   int high = n;
   while (low < high) {
       int mid = low + (high - low) / 2
       int cmp = compare_entry(&list[mid], value);
       if (cmp < 0) {
           low = mid + 1;
       } else {
            high = mid; 
       }
   }
   if (low < n) {
       int cmp = compare_entry(&list[low], value);
       if (cmp == 0) {
           return low; // found item at 'low' index
       }
   } else {
        return -1;  // not found
   } 
}