建议一种具有最少查找时间复杂度的好方法

时间:2010-04-12 04:30:29

标签: time complexity-theory lookup data-structures

我的结构有3个标识符字段和一个值字段。我有一个这些对象的列表。举一个类比,标识符字段就像是对象的主键。这3个字段唯一标识一个对象。

Class
{
   int a1;
   int a2;
   int a3;
   int value;
};

我将拥有此数据类型的1000个对象的列表。我需要通过将a1,a2和a3的值传递给查找函数来检查这些标识键值的特定值,该函数将检查是否存在具有特定值a1,a2和a3的任何对象并返回该值。实现此目标以实现最佳查找时间的最有效方法是什么?

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

您能否建议一种存储这些数据的好方法,这样可以获得最佳的查找时间?

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

我只需按键对数组进行排序,然后使用二进制搜索。

(未测试的)

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
   } 
}

绝对是最糟糕的情况,你会经历这个事情,10次,最后实际完成密钥比较中的所有比较。那是什么,85整数数学运算(加法,减法和1班)?

如果您的a1-a3的范围是0-100,那么您可以将您的密钥设为a1 * 10000 + a2 * 100 + a3,并进行单次比较,最坏的情况是63次整数运算。并且您的整个阵列都适合大多数现代处理器的缓存。它的内存效率很高。

您可以使用完美哈希或其他稀疏矩阵刻录内存。即使有一个完美的哈希,我敢打赌哈希计算本身在这个时候具有竞争力,考虑到乘法是昂贵的。显然,这会更难打到内存总线。