mjordan
13-03-2007, 00:45
Stavo leggendo il codice di VMD (http://www.ks.uiuc.edu/Research/vmd/) e mi sono imbattuto in un'implementazione di una tabella hash. Implementazione classica, se non per la funzione hash, di cui non riesco a capirne la semantica.
La struttura è tradizionale e di semplice comprensione:
typedef struct hash_t {
struct hash_node_t ** bucket;
int size;
int entries;
int downshift;
int mask;
} hash_t;
Il tipo hash_node_t è così definito:
typedef struct hash_node_t {
int data;
const char * key;
struct hash_node_t *next;
} hash_node_t;
e fin quì ci siamo.
Analizziamo ora la funzione per l'inizializzazione della tabella:
void hash_init(hash_t *tptr, int buckets) {
/* make sure we allocate something */
if (buckets == 0)
buckets = 16;
/* initialize the table */
tptr->entries = 0;
tptr->size = 2;
tptr->mask = 1;
tptr->downshift = 29;
/* ensure buckets is a power of 2 */
while (tptr->size < buckets) {
tptr->size <<= 1;
tptr->mask = (tptr->mask << 1) + 1;
tptr->downshift--;
}
/* allocate memory for table */
tptr->bucket = (hash_node_t **)calloc(tptr->size, sizeof(hash_node_t *));
}
... e la funzione per il calcolo della funzione hash:
static int hash(const hash_t * tptr, const char * key) {
int i = 0;
int hashvalue;
while (*key != '\0') {
i = (i << 3) + (*key++ - '0');
hashvalue = (((i * 1103515249) >> tptr->downshift) & tptr->mask);
if (hashvalue < 0) {
hashvalue = 0;
}
}
return hashvalue;
}
Secondo voi quale dovrebbe essere la semantica dei campi downshift, mask e dell'uso degli operatori di shift sugli interi ai fini della funzione hash? :wtf:
La struttura è tradizionale e di semplice comprensione:
typedef struct hash_t {
struct hash_node_t ** bucket;
int size;
int entries;
int downshift;
int mask;
} hash_t;
Il tipo hash_node_t è così definito:
typedef struct hash_node_t {
int data;
const char * key;
struct hash_node_t *next;
} hash_node_t;
e fin quì ci siamo.
Analizziamo ora la funzione per l'inizializzazione della tabella:
void hash_init(hash_t *tptr, int buckets) {
/* make sure we allocate something */
if (buckets == 0)
buckets = 16;
/* initialize the table */
tptr->entries = 0;
tptr->size = 2;
tptr->mask = 1;
tptr->downshift = 29;
/* ensure buckets is a power of 2 */
while (tptr->size < buckets) {
tptr->size <<= 1;
tptr->mask = (tptr->mask << 1) + 1;
tptr->downshift--;
}
/* allocate memory for table */
tptr->bucket = (hash_node_t **)calloc(tptr->size, sizeof(hash_node_t *));
}
... e la funzione per il calcolo della funzione hash:
static int hash(const hash_t * tptr, const char * key) {
int i = 0;
int hashvalue;
while (*key != '\0') {
i = (i << 3) + (*key++ - '0');
hashvalue = (((i * 1103515249) >> tptr->downshift) & tptr->mask);
if (hashvalue < 0) {
hashvalue = 0;
}
}
return hashvalue;
}
Secondo voi quale dovrebbe essere la semantica dei campi downshift, mask e dell'uso degli operatori di shift sugli interi ai fini della funzione hash? :wtf: