对于某些编译语言,是否有一个哈希表的有效实现,它将键(整数)映射到值(字符串),反之亦然?
当然,可以总是有两个表,一个用于key =>值映射,另一个用于value =>键。然而,这不会非常有效,至少在记忆方面不是这样。如果类型系统和预期用途允许,两个映射可能都在一个表中。
答案 0 :(得分:1)
这个名称是BiMap(如双向)。明显的限制是键将是不同的(如在普通字典/地图中),但值也是如此。
对于Java,有一个StackOverflow question on it,但一般建议是Guava BiMap。
对于C和C ++,Boost has a Bimap。
在内部,这是你提到的“低效”实现,它保留了两个哈希表。事情就是这样:它 效率高,并且预期使用两倍于二级查找结构的内存,并且很少有大问题。
答案 1 :(得分:0)
这是我用于bihash的数据结构: 每个条目的开销是四个整数(对于索引)。
在下面的示例中,使用typedef unsigned char Index;
,开销将是四个字符,最大表容量将为255.
/* For demonstration purposes these types are VERY SMALL.
** Normally one would use unsigned short, or unsigned int.
*/
typedef unsigned char Index;
typedef unsigned short Hashval;
/* Use the maximal representable value as sentinel value */
#define NIL ((Index)-1)
struct entry {
Index head_key /* The head-of-the-chain pointers */
, head_val; /* ... and for the values */
Index next_key /* linked list for chaining the keys */
, next_val; /* ... and for the values */
};
struct table {
unsigned totlen, keylen;
/* free points to the root of the freetree */
Index size, free;
/* The complete payload, for both keys and values.
* layout = [key0|val0|key1|val1|..] (without padding/alignment)
*/
char *data;
struct entry *entries; /* All the entries. Not pointers, but the actual entries. */
};
/* Macros for accessing the pool of payload */
#define NODE_KEY(p,n) ((p)->data + (n) * (p)->totlen)
#define NODE_VAL(p,n) ((p)->data + (n) * ((p)->totlen+(p)->keylen))
#define TH_OK 0
#define TH_KEY_NOT_FOUND 1
#define TH_VAL_NOT_FOUND 2
#define TH_BOTH_NOT_FOUND 3
#define TH_TABLE_FULL 4
#define TH_KEY_DUPLICATE 5
#define TH_VAL_DUPLICATE 6
#define TH_BOTH_DUPLICATE 7
#define TH_TOTAL_ECLIPSE 8
/********************************************/
/* Allocate and initialise the hash table.
** Note: given fixed size, the table and the payload could be statically allocated,
** (but we'd still need to do the initialisation)
*/
struct table * table_new( unsigned keylen, unsigned vallen, unsigned totcount )
{
Index idx;
struct table *this;
if (totcount > NIL) {
fprintf(stderr, "Table_new(%zu,%zu,%zu): totcount(%zu) larger than largest Index(%zu)\n"
, (size_t) keylen, (size_t) vallen, (size_t) totcount
, (size_t) totcount, ((size_t)NIL) -1 );
return NULL;
}
this = malloc (sizeof *this);
this->size = totcount;
this->keylen = keylen;
this->totlen = keylen+vallen;
this->data = malloc (totcount * this->totlen );
this->entries = malloc (totcount * sizeof *this->entries );
this->free = 0; /* start of freelist */
for( idx=0; idx < this->size; idx++ ) {
this->entries[idx].head_key = NIL;
this->entries[idx].head_val = NIL;
this->entries[idx].next_key = NIL;
this->entries[idx].next_val = idx+1; /* unused next pointer reused as freelist */
};
this-> entries[idx-1].next_val = NIL; /* end of freelist */
fprintf(stderr, "Table_new(%zu,%zu,%zu) size = %zu+%zu+%zu\n"
, (size_t) keylen, (size_t) vallen, (size_t) totcount
, sizeof *this, (size_t)totcount * this->totlen, totcount * sizeof *this->entries
);
return this;
}