有没有更快的方法来查找数据?

时间:2017-09-04 05:48:07

标签: c algorithm

这是采访问题。

我们正在开发一个k / v系统,其中一部分已经开发出来,我们需要你完成它。

已经完成的事情 -

1)返回任何字符串的散列,可以假设返回值始终是唯一的,没有碰撞,      这取决于你是否使用它

int hash(char *string);

你需要完成的事情 -

int set(char *key, char *value);
char *get(char *key);

我的回答是

struct kv {
        int key;
        char *value;
        kv *next;
};                  

struct kv *top;
struct kv *end;

void set(char *key, char *value) {
        if(top == NULL) {
                top = malloc(struct kv);
                end = top;
        }       
        sturct kv *i = top;
        int k = hash(key);
        while(i != end) {
                if(i->key == k) {
                        i->value = value;
                        return;
                }
                i = i->next;
        }
        i = malloc(struct kv);
        i->key = k;
        i->value = value;
        end = i;
}       

char *get(char *key) {
        if(top == NULL) {
                return NULL;
        }
        sturct kv *i = top;
        int k = hash(key);
        while(i != end) {
                if(i->key == k) {
                        return i->value;
                }       
                i = i->next;
        }       
        return NULL;
}   

问: - 有更快的方法吗?您认为最快的方式是什么?

2 个答案:

答案 0 :(得分:1)

您所做的是创建一个链接列表来存储键值对。但正如您所看到的,搜索复杂度为O(n)。您可以通过创建哈希表来加快速度。您已经有一个保证0冲突的哈希函数。

你能做的是

char* hash_tables[RANGE_OF_HASH] = {NULL}; // Your interviewer should provide you RANGE_OF_HASH

然后您的setget成为 -

void set(char* key, char* value) {
    hash_table[hash(key)] = value; // Can do this because no collisions are guaranteed. 
}

char* get(char* key) {
    return hash_table[hash(key)];
}

在这种情况下,由于您不必迭代所有插入的密钥,get复杂度为O(1)(同样为set)。

但是你需要意识到这通常比你的方法占用更多的空间。 您的方法占用O(n)空间但占用O(RANGE_OF_HASH)。在内存是约束的情况下,这可能是不可接受的。

如果RANGE_OF_HASH非常大(如INT_MAX)并且您没有足够的内存用于hash_table,则可以创建多级哈希表。

例如,您的主hash_table只有256个广告位。每个条目将指向256个条目的另一个哈希表,依此类推。你将会有 做一些掩码来获取每个级别的哈希值。您可以按需分配每个级别。这样您就可以最大限度地减少内存使用量。

答案 1 :(得分:1)

有很多很好的方法可以做到这一点。这是一个小阅读清单,请仔细阅读。肯定有更多我不知道的事情。

  • 使用binary search对列表进行排序 - 根据使用模式,可以快速或慢速构建,但查找保证为O(log(N))。
  • Hash table - 快速,平均接近O(1),最坏情况下为所有操作的O(N)。
  • Binary tree - 最佳情况O(log(N)),最差情况O(N)。
    • AVL tree - 保证所有操作的O(log(N))。
    • Red-black tree - 与AVL类似,但会以更快的插入速度换取查找速度。
  • Trie - 所有操作都是真的O(1),代价是更多的内存使用。

在此之后,休息一下,振作起来,深入研究this article about computer memory。这已经是高级内容,并且会向您显示有时候更糟糕的big-O度量在实际场景中实际上可以表现得更好。这完全取决于将会有什么样的数据以及使用模式是什么。