1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "hash_map.h"
#define INITIAL_SIZE (16)
#define LOAD_FACTOR_THRESHOLD (0.75)
typedef struct Pair {
char *key;
int value;
struct Pair *next;
} Pair;
typedef struct HashMap {
Pair **table;
size_t size;
size_t count;
} HashMap;
static unsigned int hash(const char *key, size_t size) {
unsigned int hash_value = 0;
while (*key)hash_value = (hash_value * 31) + *key++;
return hash_value % size;
}
hashmap_t hashmap_create(void) {
HashMap *map = (HashMap *)malloc(sizeof(HashMap));
assert(map);
map->size = INITIAL_SIZE;
map->count = 0;
map->table = (Pair **)calloc(map->size, sizeof(Pair *));
assert(map->table);
return map;
}
static void resize(hashmap_t map) {
size_t new_size = ((HashMap*)map)->size * 2;
Pair **new_table = (Pair **)calloc(new_size, sizeof(Pair *));
assert(new_table);
for (size_t i = 0; i < ((HashMap*)map)->size; ++i) {
Pair *pair = ((HashMap*)map)->table[i];
while (pair) {
unsigned int index = hash(pair->key, new_size);
Pair *next = pair->next;
pair->next = new_table[index];
new_table[index] = pair;
pair = next;
}
}
free(((HashMap*)map)->table);
((HashMap*)map)->table = new_table;
((HashMap*)map)->size = new_size;
}
void hashmap_insert(hashmap_t map, const char *key, int value) {
if ((float)((HashMap*)map)->count / ((HashMap*)map)->size > LOAD_FACTOR_THRESHOLD) resize(((HashMap*)map));
unsigned int index = hash(key, ((HashMap*)map)->size);
Pair *new_pair = (Pair *)malloc(sizeof(Pair));
assert(new_pair);
new_pair->key = strdup(key);
assert(new_pair->key);
new_pair->value = value;
new_pair->next = ((HashMap*)map)->table[index];
((HashMap*)map)->table[index] = new_pair;
((HashMap*)map)->count++;
}
int *hashmap_get(hashmap_t map, const char *key) {
unsigned int index = hash(key, ((HashMap*)map)->size);
Pair *pair = ((HashMap*)map)->table[index];
while (pair) {
if (strcmp(pair->key, key) == 0) return &pair->value;
pair = pair->next;
}
return NULL;
}
void hashmap_delete(hashmap_t map, const char *key) {
unsigned int index = hash(key, ((HashMap*)map)->size);
Pair *pair = ((HashMap*)map)->table[index];
Pair *prev = NULL;
while (pair) {
if (strcmp(pair->key, key) == 0) {
if (prev) prev->next = pair->next;
else ((HashMap*)map)->table[index] = pair->next;
free(pair->key);
free(pair);
((HashMap*)map)->count--;
return;
}
prev = pair;
pair = pair->next;
}
}
void hashmap_free(hashmap_t map) {
for (size_t i = 0; i < ((HashMap*)map)->size; ++i) {
Pair *pair = ((HashMap*)map)->table[i];
while (pair){
Pair *temp = pair;
pair = pair->next;
free(temp->key);
free(temp);
}
}
free(((HashMap*)map)->table);
free(((HashMap*)map));
}
|