1 /* ------------------------------------------------------
2 * Open-addressed hash using double hash probing
5 * h(k, i) = ( h1(k) + i*h2(k) ) mod m
7 * requires: 1) m must be a power of two
8 * 2) h2(k) must return an odd number
10 * Besed on code published in _Mastering Algorithms in C_
11 * by Kyle Loudon (O'Reilly 1999).
12 * Modified by Philip Kovacs (kovacsp3@comcast.net)
15 * ------------------------------------------------------ */
24 /* Create and initialize a hash table on the heap.
25 Returns 0 on success, -1 otherwise. */
26 int hash_create( hash_table_t *p_hash_table,
28 int (*p_hash_fun1)(const void *p_data),
29 int (*p_hash_fun2)(const void *p_data),
30 int (*p_match_fun)(const void *p_data1, const void *p_data2),
31 void (*p_destroy_fun)(void *p_data)
34 if ( ( p_hash_table->pp_table = (void **)calloc(positions, sizeof(void *))) == NULL )
37 p_hash_table->positions = positions;
38 p_hash_table->size = 0;
39 p_hash_table->vacated = 0;
41 /* sentinel address indicating a vacated slot */
42 p_hash_table->p_vacated = &p_hash_table->sentinel_vacated;
44 p_hash_table->p_hash_fun1 = p_hash_fun1;
45 p_hash_table->p_hash_fun2 = p_hash_fun2;
47 p_hash_table->p_match_fun = p_match_fun;
48 p_hash_table->p_destroy_fun = p_destroy_fun;
54 /* Destroy a hash table */
55 void hash_destroy( hash_table_t *p_hash_table )
62 /* Destroy the elements the hash points to, if a destroy function was provided */
63 if (p_hash_table->p_destroy_fun != NULL) {
65 for (i = 0; i < p_hash_table->positions; i++) {
67 if ( p_hash_table->pp_table[i] != NULL && p_hash_table->pp_table[i] != p_hash_table->p_vacated )
68 p_hash_table->p_destroy_fun( p_hash_table->pp_table[i] );
72 free( p_hash_table->pp_table );
73 memset( p_hash_table, 0, sizeof(hash_table_t) );
78 /* Insert an element into a hash table.
79 Returns 0 on successful insert, 1 if data already in hash and -1 if unable to insert. */
80 int hash_insert( hash_table_t *p_hash_table, const void *p_data )
84 int hashed_1, hashed_2;
89 if ( p_hash_table->size == p_hash_table->positions )
92 temp = (void *)p_data;
94 if ( hash_lookup( p_hash_table, &temp ) == 0 )
97 /* Loudon's original algorithm needlessly repeated running the hash algorithms with each iteration
98 to find a slot. Just running the hash algorithms once is enough since they are deterministic. */
99 hashed_1 = p_hash_table->p_hash_fun1( p_data );
100 hashed_2 = p_hash_table->p_hash_fun2( p_data );
102 for ( i = 0; i < p_hash_table->positions; i++ ) {
104 position = ( hashed_1 + (i * hashed_2) ) % p_hash_table->positions;
106 printf("--- hash_insert: probe %d, position %d\n",i,position);
109 if ( p_hash_table->pp_table[ position ] == NULL ) /* empty slot */
111 p_hash_table->pp_table[ position ] = (void *)p_data;
112 p_hash_table->size++;
116 if ( p_hash_table->pp_table[ position ] == p_hash_table->p_vacated ) /* vacated slot */
118 p_hash_table->pp_table[ position ] = (void *)p_data;
119 p_hash_table->size++;
120 p_hash_table->vacated--;
125 /* hash functions not selected correctly since the above algorithm should visit all slots in the hash. */
129 /* Delete an element from a hash table.
130 Returns 0 on successful delete, -1 if not found. */
131 int hash_remove( hash_table_t *p_hash_table, void **pp_data)
134 int hashed_1, hashed_2;
136 if ( !p_hash_table || !pp_data )
139 hashed_1 = p_hash_table->p_hash_fun1( *pp_data );
140 hashed_2 = p_hash_table->p_hash_fun2( *pp_data );
142 for (i = 0; i < p_hash_table->positions; i++) {
144 position= ( hashed_1 + (i * hashed_2) ) % p_hash_table->positions;
146 printf("--- hash_remove: probe %d, position %d\n",i,position);
149 if ( p_hash_table->pp_table[ position ] == NULL ) {
155 else if ( p_hash_table->pp_table[ position ] == p_hash_table->p_vacated ) {
161 else if ( p_hash_table->p_match_fun( p_hash_table->pp_table[ position ], *pp_data)) {
163 *pp_data = p_hash_table->pp_table[ position ];
164 p_hash_table->pp_table[ position ] = p_hash_table->p_vacated;
165 p_hash_table->vacated++;
166 p_hash_table->size--;
174 /* Lookup an element in a hash table.
175 Returns 0 if found (data passed back byref), -1 if not found. */
176 int hash_lookup(const hash_table_t *p_hash_table, void **pp_data)
179 int hashed_1, hashed_2;
181 if ( !p_hash_table || !pp_data )
184 hashed_1 = p_hash_table->p_hash_fun1( *pp_data );
185 hashed_2 = p_hash_table->p_hash_fun2( *pp_data );
187 for (i = 0; i < p_hash_table->positions; i++) {
189 position= ( hashed_1 + (i * hashed_2) ) % p_hash_table->positions;
191 printf("--- hash_lookup: probe %d, position %d\n",i,position);
193 if ( p_hash_table->pp_table[ position ] == NULL ) {
199 else if ( p_hash_table->p_match_fun(p_hash_table->pp_table[ position ], *pp_data) ) {
201 *pp_data = p_hash_table->pp_table[ position ];