-
Notifications
You must be signed in to change notification settings - Fork 273
Expand file tree
/
Copy pathHashTable.c
More file actions
324 lines (255 loc) · 7.21 KB
/
Copy pathHashTable.c
File metadata and controls
324 lines (255 loc) · 7.21 KB
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/**
* @file HashTable.c
* @brief Hash Table implementation with separate chaining
*
* Time Complexity:
* - Insert: O(1) averege, O(n) worst
* - Search: O(1) averege, O(n) worst
* - Delete: O(1) averege, O(n) worst
*
* Space Complexity: O(n)
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
/*Node for linked list (handles collision)*/
typedef struct node {
int value;
struct node *next;
} Node;
/*Hash table structure*/
typedef struct hashtable {
Node **table; // Array of linked list
size_t size; // Table size
} HashTable;
/* ============ FUNCTION DECLARATIONS ============ */
// Creates new hash table with given size
HashTable *initHashTable(size_t size);
/// @brief Hash function maps value to table index
/// @param size_of_hashTable size of the hash table
/// @param value value to be inserted
/// @return index of the table
size_t hash(size_t size_of_hashTable, int value);
/// @brief Removes value from table (allows duplicates)
/// @param hashTable pointer to hash table
/// @param value value that you want to remove
/// @return 0 on success, -1 if not found
int hashTableRemove(HashTable *hashTable, int value);
/// @brief Creates new linked list node
/// @param value value to be inserted
/// @return pointer to created node
Node *createNode(int value);
/// @brief Finds value on the hash table
/// @param hashTable pointer to hash table
/// @param value value to be searched
/// @return A pointer to Node's value on success, NULL if not found
Node *hashTableFind(HashTable *hashTable, int value);
/// @brief Inserts value in table (allow duplicates)
/// @param hashTable pointer to hash table
/// @param value value to be inserted
void hashTableInsert(HashTable *hashTable, int value);
/// @brief Print only occupied buckets
/// @param hashTable pointer to hash table
void printHashTable(HashTable *hashTable);
/// @brief Print all buckets (including empty)
/// @param hashTable pointer to hash table
void printAllHashTable(HashTable *hashTable);
/// @brief Prints specific bucket index
/// @param hashTable pointer to hash table
/// @param index index to be printed
void printIndexHashTable(HashTable *hashTable, size_t index);
/// @brief Removes all elements but keeps table structure
/// @param hashTable pointer to hash table
void cleanHashTable(HashTable *hashTable);
/// @brief Frees all memory and sets pointer to NULL
/// @param[in,out] hashTable Address of hash table pointer. Modified to NULL on
/// success
void destroyHashTable(HashTable **hashTable);
int main() {
// EXAMPLE USAGE
HashTable *ht = initHashTable(10);
hashTableInsert(ht, 42);
hashTableInsert(ht, 52); // Collision with 42's bucket
hashTableInsert(ht, -5);
printHashTable(ht);
cleanHashTable(ht);
destroyHashTable(&ht);
return 0;
}
/* ============ IMPLEMENTATIONS ============ */
// Hash function using multiplicative method
size_t hash(size_t size_of_hashTable, int value) {
unsigned int u_val = (unsigned int)(value < 0 ? -value : value);
size_t index = u_val * 97 + 10213;
return (size_t)index % size_of_hashTable;
}
HashTable *initHashTable(size_t size) {
HashTable *newHashTable = (HashTable *)malloc(sizeof(HashTable));
if (!newHashTable) {
fprintf(stderr, "Malloc Error: could not allocate HashTable");
exit(EXIT_FAILURE);
}
newHashTable->table =
(Node **)calloc(size, sizeof(Node)); // calloc zeroes memory
newHashTable->size = size;
if (!newHashTable->table) {
fprintf(stderr, "Malloc Error: could not allocate HashTable->table");
free(newHashTable);
exit(EXIT_FAILURE);
}
return newHashTable;
}
int hashTableRemove(HashTable *hashTable, int value) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized\n");
return -1;
}
size_t index = hash(hashTable->size, value);
Node *temp = hashTable->table[index];
Node *prev = NULL;
while (temp) {
if (temp->value == value) {
// Remove from list
if (!prev) {
hashTable->table[index] = temp->next;
} else {
prev->next = temp->next;
}
free(temp);
return 0;
}
prev = temp;
temp = temp->next;
}
return -1; // Not found
}
Node *createNode(int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (!newNode) {
fprintf(stderr, "Could not create a new node");
return NULL;
}
newNode->value = value;
newNode->next = NULL;
return newNode;
}
Node *hashTableFind(HashTable *hashTable, int value) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized");
return NULL;
}
size_t index = hash(hashTable->size, value);
Node *aux = hashTable->table[index];
while (aux) { // while aux != NULL
if (aux->value == value)
return aux;
aux = aux->next;
}
return NULL;
}
void hashTableInsert(HashTable *hashTable, int value) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized");
return;
}
size_t index = hash(hashTable->size, value);
Node *newNode = createNode(value);
if (!newNode) {
fprintf(stderr, "Can not insert null node");
return;
}
// Insert at head of linked list
newNode->next = hashTable->table[index];
hashTable->table[index] = newNode;
}
void printHashTable(HashTable *hashTable) {
if (!hashTable) {
return;
}
for (size_t i = 0; i < hashTable->size; i++) {
if (hashTable->table[i] != NULL) {
Node *temp = hashTable->table[i];
printf("Index %zu: ", i);
while (temp != NULL) {
printf("-> %d", temp->value);
temp = temp->next;
}
puts("\n");
}
}
}
void printAllHashTable(HashTable *hashTable) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized");
return;
}
for (size_t i = 0; i < hashTable->size; i++) {
Node *temp = hashTable->table[i];
printf("Index %zu ", i);
while (temp) {
printf("-> %d", temp->value);
temp = temp->next;
}
puts("\n");
}
}
void printIndexHashTable(HashTable *hashTable, size_t index) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized");
return;
}
Node *temp = hashTable->table[index];
printf("Index %zu ", index);
while (temp) {
printf("-> %d", temp->value);
temp = temp->next;
}
}
void cleanHashTable(HashTable *hashTable) {
if (!hashTable || !hashTable->table) {
fprintf(stderr, "HashTable not initialized");
return;
}
for (size_t i = 0; i < hashTable->size; i++) {
if (hashTable->table[i]) {
Node *temp = hashTable->table[i];
Node *next = NULL;
while (temp) {
next = temp->next;
free(temp);
temp = next;
}
hashTable->table[i] = NULL;
}
}
}
void destroyHashTable(HashTable **hashTable) {
if (!hashTable) {
fprintf(stderr, "HashTable not initialized");
return;
}
HashTable *h = *hashTable;
if (!h) {
*hashTable = NULL;
return;
}
if (!h->table) {
free(h);
*hashTable = NULL;
return;
}
for (size_t i = 0; i < h->size; i++) {
if (h->table[i]) {
Node *temp = h->table[i];
Node *next = NULL;
while (temp) {
next = temp->next;
free(temp);
temp = next;
}
}
}
free(h->table);
free(h);
*hashTable = NULL;
}