static void grow_hash_table (struct hash_table *ht) { struct mapping *old_mappings = ht->mappings; struct mapping *old_end = ht->mappings + ht->size; struct mapping *mp, *mappings; int newsize; newsize = prime_size (ht->size * 2); #if 0 printf ("growing from %d to %d\n", ht->size, newsize); #endif ht->size = newsize; ht->resize_threshold = newsize * 3 / 4; mappings = xmalloc (ht->size * sizeof (struct mapping)); memset (mappings, '\0', ht->size * sizeof (struct mapping)); ht->mappings = mappings; for (mp = old_mappings; mp < old_end; mp++) if (!EMPTY_MAPPING_P (mp)) { struct mapping *new_mp = mappings + HASH_POSITION (ht, mp->key); /* We don't need to call test function and worry about collisions because all the keys come from the hash table and are therefore guaranteed to be unique. */ LOOP_NON_EMPTY (new_mp, mappings, newsize) ; *new_mp = *mp; } xfree (old_mappings); }
struct hash_table * hash_table_new (int items, unsigned long (*hash_function) (const void *), int (*test_function) (const void *, const void *)) { int size; struct hash_table *ht = xnew (struct hash_table); ht->hash_function = hash_function ? hash_function : hash_pointer; ht->test_function = test_function ? test_function : cmp_pointer; /* If the size of struct hash_table ever becomes a concern, this field can go. (Wget doesn't create many hashes.) */ ht->prime_offset = 0; /* Calculate the size that ensures that the table will store at least ITEMS keys without the need to resize. */ size = 1 + items / HASH_MAX_FULLNESS; size = prime_size (size, &ht->prime_offset); ht->size = size; ht->resize_threshold = size * HASH_MAX_FULLNESS; /*assert (ht->resize_threshold >= items);*/ ht->cells = xnew_array (struct cell, ht->size); /* Mark cells as empty. We use 0xff rather than 0 to mark empty keys because it allows us to use NULL/0 as keys. */ memset (ht->cells, INVALID_PTR_CHAR, size * sizeof (struct cell)); ht->count = 0; return ht; }
int createhash(hash* h,int defaultsize,hashfun_t hf) { h->prime_offset=0; h->size=prime_size(defaultsize,&h->prime_offset); if((h->addr=(cell*)malloc(sizeof(cell)*h->size))==0) return 1; h->hashfunction=hf?hf:defaulthash; h->currentsize=0; h->tombsize=0; int i; for(i=0;i<h->size;++i) //初始化为空 (h->addr+i)->stat=EMPTY; return 0; }
/* *增长过程,把原来表的size和prime_size变动了。并更新了存储空间。currentsize不变,tombsize清零 */ static int grow(hash* h) { int oldsize=h->size; h->size=prime_size(oldsize*hash_resize_factor,&h->prime_offset); //更新size...函数调用prime_size还会自动更新prime_offset cell* oldaddr=h->addr; if((h->addr=(cell*)malloc(h->size*sizeof(cell)))==0) //更新存储空间 return 1; int i; for(i=0;i<h->size;++i) (h->addr+i)->stat=EMPTY; //初始化新表 h->currentsize=0; //currentsize计数清零 for(i=0;i<oldsize;++i) //把原来表的数据转到新存储空间 { if((oldaddr+i)->stat==OCCUPY) push(h,(oldaddr+i)->key,(oldaddr+i)->value); //这里会更新currentsize计数 } free(oldaddr); //销毁原来的存储空间 h->tombsize=0; //tomb计数清0 return 0; }
struct hash_table * hash_table_new (int initial_size, unsigned long (*hash_function) (const void *), int (*test_function) (const void *, const void *)) { struct hash_table *ht = (struct hash_table *)xmalloc (sizeof (struct hash_table)); ht->hash_function = hash_function; ht->test_function = test_function; ht->size = prime_size (initial_size); ht->resize_threshold = ht->size * 3 / 4; ht->count = 0; ht->mappings = xmalloc (ht->size * sizeof (struct mapping)); memset (ht->mappings, '\0', ht->size * sizeof (struct mapping)); return ht; }
static void grow_hash_table (struct hash_table *ht) { hashfun_t hasher = ht->hash_function; struct cell *old_cells = ht->cells; struct cell *old_end = ht->cells + ht->size; struct cell *c, *cells; int newsize; newsize = prime_size (ht->size * HASH_RESIZE_FACTOR, &ht->prime_offset); #if 0 printf ("growing from %d to %d; fullness %.2f%% to %.2f%%\n", ht->size, newsize, 100.0 * ht->count / ht->size, 100.0 * ht->count / newsize); #endif ht->size = newsize; ht->resize_threshold = newsize * HASH_MAX_FULLNESS; cells = xnew_array (struct cell, newsize); memset (cells, INVALID_PTR_CHAR, newsize * sizeof (struct cell)); ht->cells = cells; for (c = old_cells; c < old_end; c++) if (CELL_OCCUPIED (c)) { struct cell *new_c; /* We don't need to test for uniqueness of keys because they come from the hash table and are therefore known to be unique. */ new_c = cells + HASH_POSITION (c->key, hasher, newsize); FOREACH_OCCUPIED_ADJACENT (new_c, cells, newsize) ; *new_c = *c; } xfree (old_cells); }