@@ -231,27 +231,25 @@ int round_up_pow2(int v)
231
231
*
232
232
* Return: The pointer of created hashmap.
233
233
*/
234
- hashmap_t * hashmap_create (int size )
234
+ hashmap_t * hashmap_create (int cap )
235
235
{
236
236
hashmap_t * map = malloc (sizeof (hashmap_t ));
237
237
238
238
if (!map ) {
239
- printf ("Failed to allocate hashmap_t with size %d\n" , size );
239
+ printf ("Failed to allocate hashmap_t with capacity %d\n" , cap );
240
240
return NULL ;
241
241
}
242
242
243
- map -> size = round_up_pow2 (size );
244
- map -> buckets = malloc (map -> size * sizeof (hashmap_node_t * ));
243
+ map -> size = 0 ;
244
+ map -> cap = round_up_pow2 (cap );
245
+ map -> buckets = calloc (map -> cap , sizeof (hashmap_node_t * ));
245
246
246
247
if (!map -> buckets ) {
247
248
printf ("Failed to allocate buckets in hashmap_t\n" );
248
249
free (map );
249
250
return NULL ;
250
251
}
251
252
252
- for (int i = 0 ; i < map -> size ; i ++ )
253
- map -> buckets [i ] = 0 ;
254
-
255
253
return map ;
256
254
}
257
255
@@ -290,6 +288,47 @@ hashmap_node_t *hashmap_node_new(char *key, void *val)
290
288
return node ;
291
289
}
292
290
291
+ void hashmap_rehash (hashmap_t * map )
292
+ {
293
+ if (!map )
294
+ return ;
295
+
296
+ int old_cap = map -> cap ;
297
+ hashmap_node_t * * old_buckets = map -> buckets ;
298
+
299
+ map -> cap *= 2 ;
300
+ map -> buckets = calloc (map -> cap , sizeof (hashmap_node_t * ));
301
+
302
+ if (!map -> buckets ) {
303
+ printf ("Failed to allocate new buckets in hashmap_t\n" );
304
+ map -> buckets = old_buckets ;
305
+ map -> cap = old_cap ;
306
+ return ;
307
+ }
308
+
309
+ for (int i = 0 ; i < old_cap ; i ++ ) {
310
+ hashmap_node_t * cur = old_buckets [i ], * next , * target_cur ;
311
+
312
+ while (cur ) {
313
+ next = cur -> next ;
314
+ cur -> next = NULL ;
315
+ int index = hashmap_hash_index (map -> cap , cur -> key );
316
+ target_cur = map -> buckets [index ];
317
+
318
+ if (!target_cur ) {
319
+ map -> buckets [index ] = cur ;
320
+ } else {
321
+ cur -> next = target_cur ;
322
+ map -> buckets [index ] = cur ;
323
+ }
324
+
325
+ cur = next ;
326
+ }
327
+ }
328
+
329
+ free (old_buckets );
330
+ }
331
+
293
332
/**
294
333
* hashmap_put() - puts a key-value pair into given hashmap.
295
334
* If key already contains a value, then replace it with new
@@ -304,42 +343,59 @@ void hashmap_put(hashmap_t *map, char *key, void *val)
304
343
if (!map )
305
344
return ;
306
345
307
- int index = hashmap_hash_index (map -> size , key );
308
- hashmap_node_t * cur = map -> buckets [index ];
346
+ int index = hashmap_hash_index (map -> cap , key );
347
+ hashmap_node_t * cur = map -> buckets [index ],
348
+ * new_node = hashmap_node_new (key , val );
309
349
310
350
if (!cur ) {
311
- map -> buckets [index ] = hashmap_node_new ( key , val ) ;
351
+ map -> buckets [index ] = new_node ;
312
352
} else {
313
353
while (cur -> next )
314
354
cur = cur -> next ;
315
- cur -> next = hashmap_node_new ( key , val ) ;
355
+ cur -> next = new_node ;
316
356
}
317
357
318
- /* TODO: Rehash if size exceeds size * load factor */
358
+ map -> size ++ ;
359
+ if ((map -> cap >> 2 ) * 3 <= map -> size )
360
+ hashmap_rehash (map );
319
361
}
320
362
321
363
/**
322
- * hashmap_get () - gets value from hashmap from given key.
364
+ * hashmap_get_node () - gets key- value pair node from hashmap from given key.
323
365
* @map: The hashmap to be looked up. Must no be NULL.
324
366
* @key: The key string. May be NULL.
325
367
*
326
368
* Return: The look up result, if the key-value pair entry
327
- * exists, then returns its value's address , NULL otherwise.
369
+ * exists, then returns address of itself , NULL otherwise.
328
370
*/
329
- void * hashmap_get (hashmap_t * map , char * key )
371
+ hashmap_node_t * hashmap_get_node (hashmap_t * map , char * key )
330
372
{
331
373
if (!map )
332
374
return NULL ;
333
375
334
- int index = hashmap_hash_index (map -> size , key );
376
+ int index = hashmap_hash_index (map -> cap , key );
335
377
336
378
for (hashmap_node_t * cur = map -> buckets [index ]; cur ; cur = cur -> next )
337
379
if (!strcmp (cur -> key , key ))
338
- return cur -> val ;
380
+ return cur ;
339
381
340
382
return NULL ;
341
383
}
342
384
385
+ /**
386
+ * hashmap_get() - gets value from hashmap from given key.
387
+ * @map: The hashmap to be looked up. Must no be NULL.
388
+ * @key: The key string. May be NULL.
389
+ *
390
+ * Return: The look up result, if the key-value pair entry
391
+ * exists, then returns its value's address, NULL otherwise.
392
+ */
393
+ void * hashmap_get (hashmap_t * map , char * key )
394
+ {
395
+ hashmap_node_t * node = hashmap_get_node (map , key );
396
+ return node ? node -> val : NULL ;
397
+ }
398
+
343
399
/**
344
400
* hashmap_contains() - checks if the key-value pair entry exists
345
401
* from given key.
@@ -351,7 +407,7 @@ void *hashmap_get(hashmap_t *map, char *key)
351
407
*/
352
408
bool hashmap_contains (hashmap_t * map , char * key )
353
409
{
354
- return hashmap_get (map , key );
410
+ return hashmap_get_node (map , key );
355
411
}
356
412
357
413
/**
@@ -368,7 +424,8 @@ void hashmap_free(hashmap_t *map)
368
424
for (hashmap_node_t * cur = map -> buckets [i ], * next ; cur ; cur = next ) {
369
425
next = cur -> next ;
370
426
free (cur -> key );
371
- free (cur -> val );
427
+ if (cur -> val )
428
+ free (cur -> val );
372
429
free (cur );
373
430
cur = next ;
374
431
}
0 commit comments