Skip to content

Commit 1b31053

Browse files
committed
Testing
1 parent 1235000 commit 1b31053

2 files changed

Lines changed: 326 additions & 2 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,8 +2621,8 @@ In order to achieve greater coverage and encourage more people to contribute to
26212621
<tr>
26222622
<td><a href="https://en.wikipedia.org/wiki/Hash_table">Hash Table</a></td>
26232623
<td> <!-- C -->
2624-
<a href="./CONTRIBUTING.md">
2625-
<img align="center" height="25" src="./logos/github.svg" />
2624+
<a href="./src/c/HashTable.c">
2625+
<img align="center" height="25" src="./logos/c.svg" />
26262626
</a>
26272627
</td>
26282628
<td> <!-- C++ -->

src/c/HashTable.c

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
/**
2+
* @file HashTable.c
3+
* @brief Hash Table implementation with separate chaining
4+
*
5+
* Time Complexity:
6+
* - Insert: O(1) averege, O(n) worst
7+
* - Search: O(1) averege, O(n) worst
8+
* - Delete: O(1) averege, O(n) worst
9+
*
10+
* Space Complexity: O(n)
11+
*/
12+
13+
#include <limits.h>
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
17+
/*Node for linked list (handles collision)*/
18+
typedef struct node {
19+
int value;
20+
struct node *next;
21+
} Node;
22+
23+
/*Hash table structure*/
24+
typedef struct hashtable {
25+
Node **table; // Array of linked list
26+
size_t size; // Table size
27+
} HashTable;
28+
29+
/* ============ FUNCTION DECLARATIONS ============ */
30+
31+
// Creates new hash table with given size
32+
HashTable *initHashTable(size_t size);
33+
34+
/// @brief Hash function maps value to table index
35+
/// @param size_of_hashTable size of the hash table
36+
/// @param value value to be inserted
37+
/// @return index of the table
38+
size_t hash(size_t size_of_hashTable, int value);
39+
40+
/// @brief Removes value from table (allows duplicates)
41+
/// @param hashTable pointer to hash table
42+
/// @param value value that you want to remove
43+
/// @return 0 on success, -1 if not found
44+
int hashTableRemove(HashTable *hashTable, int value);
45+
46+
/// @brief Creates new linked list node
47+
/// @param value value to be inserted
48+
/// @return pointer to created node
49+
Node *createNode(int value);
50+
51+
/// @brief Finds value on the hash table
52+
/// @param hashTable pointer to hash table
53+
/// @param value value to be searched
54+
/// @return A pointer to Node's value on success, NULL if not found
55+
Node *hashTableFind(HashTable *hashTable, int value);
56+
57+
/// @brief Inserts value in table (allow duplicates)
58+
/// @param hashTable pointer to hash table
59+
/// @param value value to be inserted
60+
void hashTableInsert(HashTable *hashTable, int value);
61+
62+
/// @brief Print only occupied buckets
63+
/// @param hashTable pointer to hash table
64+
void printHashTable(HashTable *hashTable);
65+
66+
/// @brief Print all buckets (including empty)
67+
/// @param hashTable pointer to hash table
68+
void printAllHashTable(HashTable *hashTable);
69+
70+
/// @brief Prints specific bucket index
71+
/// @param hashTable pointer to hash table
72+
/// @param index index to be printed
73+
void printIndexHashTable(HashTable *hashTable, size_t index);
74+
75+
/// @brief Removes all elements but keeps table structure
76+
/// @param hashTable pointer to hash table
77+
void cleanHashTable(HashTable *hashTable);
78+
79+
/// @brief Frees all memory and sets pointer to NULL
80+
/// @param[in,out] hashTable Address of hash table pointer. Modified to NULL on
81+
/// success
82+
void destroyHashTable(HashTable **hashTable);
83+
84+
int main() {
85+
86+
// EXAMPLE USAGE
87+
88+
HashTable *ht = initHashTable(10);
89+
90+
hashTableInsert(ht, 42);
91+
hashTableInsert(ht, 52); // Collision with 42's bucket
92+
hashTableInsert(ht, -5);
93+
94+
printHashTable(ht);
95+
96+
cleanHashTable(ht);
97+
destroyHashTable(&ht);
98+
99+
return 0;
100+
}
101+
102+
/* ============ IMPLEMENTATIONS ============ */
103+
104+
// Hash function using multiplicative method
105+
size_t hash(size_t size_of_hashTable, int value) {
106+
unsigned int u_val = (unsigned int)(value < 0 ? -value : value);
107+
size_t index = u_val * 97 + 10213;
108+
return (size_t)index % size_of_hashTable;
109+
}
110+
111+
HashTable *initHashTable(size_t size) {
112+
HashTable *newHashTable = (HashTable *)malloc(sizeof(HashTable));
113+
114+
if (!newHashTable) {
115+
fprintf(stderr, "Malloc Error: could not allocate HashTable");
116+
exit(EXIT_FAILURE);
117+
}
118+
119+
newHashTable->table =
120+
(Node **)calloc(size, sizeof(Node)); // calloc zeroes memory
121+
newHashTable->size = size;
122+
123+
if (!newHashTable->table) {
124+
fprintf(stderr, "Malloc Error: could not allocate HashTable->table");
125+
free(newHashTable);
126+
exit(EXIT_FAILURE);
127+
}
128+
129+
return newHashTable;
130+
}
131+
132+
int hashTableRemove(HashTable *hashTable, int value) {
133+
if (!hashTable || !hashTable->table) {
134+
fprintf(stderr, "HashTable not initialized\n");
135+
return -1;
136+
}
137+
138+
size_t index = hash(hashTable->size, value);
139+
Node *temp = hashTable->table[index];
140+
Node *prev = NULL;
141+
142+
while (temp) {
143+
144+
if (temp->value == value) {
145+
// Remove from list
146+
if (!prev) {
147+
hashTable->table[index] = temp->next;
148+
149+
} else {
150+
prev->next = temp->next;
151+
}
152+
free(temp);
153+
return 0;
154+
}
155+
156+
prev = temp;
157+
temp = temp->next;
158+
}
159+
return -1; // Not found
160+
}
161+
162+
Node *createNode(int value) {
163+
Node *newNode = (Node *)malloc(sizeof(Node));
164+
165+
if (!newNode) {
166+
fprintf(stderr, "Could not create a new node");
167+
return NULL;
168+
}
169+
170+
newNode->value = value;
171+
newNode->next = NULL;
172+
173+
return newNode;
174+
}
175+
176+
Node *hashTableFind(HashTable *hashTable, int value) {
177+
if (!hashTable || !hashTable->table) {
178+
fprintf(stderr, "HashTable not initialized");
179+
return NULL;
180+
}
181+
182+
size_t index = hash(hashTable->size, value);
183+
Node *aux = hashTable->table[index];
184+
185+
while (aux) { // while aux != NULL
186+
187+
if (aux->value == value)
188+
return aux;
189+
190+
aux = aux->next;
191+
}
192+
return NULL;
193+
}
194+
195+
void hashTableInsert(HashTable *hashTable, int value) {
196+
197+
if (!hashTable || !hashTable->table) {
198+
fprintf(stderr, "HashTable not initialized");
199+
return;
200+
}
201+
202+
size_t index = hash(hashTable->size, value);
203+
Node *newNode = createNode(value);
204+
205+
if (!newNode) {
206+
fprintf(stderr, "Can not insert null node");
207+
return;
208+
}
209+
210+
// Insert at head of linked list
211+
newNode->next = hashTable->table[index];
212+
hashTable->table[index] = newNode;
213+
}
214+
215+
void printHashTable(HashTable *hashTable) {
216+
if (!hashTable) {
217+
return;
218+
}
219+
220+
for (size_t i = 0; i < hashTable->size; i++) {
221+
if (hashTable->table[i] != NULL) {
222+
Node *temp = hashTable->table[i];
223+
224+
printf("Index %zu: ", i);
225+
while (temp != NULL) {
226+
printf("-> %d", temp->value);
227+
temp = temp->next;
228+
}
229+
puts("\n");
230+
}
231+
}
232+
}
233+
234+
void printAllHashTable(HashTable *hashTable) {
235+
if (!hashTable || !hashTable->table) {
236+
fprintf(stderr, "HashTable not initialized");
237+
return;
238+
}
239+
240+
for (size_t i = 0; i < hashTable->size; i++) {
241+
Node *temp = hashTable->table[i];
242+
printf("Index %zu ", i);
243+
244+
while (temp) {
245+
printf("-> %d", temp->value);
246+
temp = temp->next;
247+
}
248+
puts("\n");
249+
}
250+
}
251+
252+
void printIndexHashTable(HashTable *hashTable, size_t index) {
253+
if (!hashTable || !hashTable->table) {
254+
fprintf(stderr, "HashTable not initialized");
255+
return;
256+
}
257+
258+
Node *temp = hashTable->table[index];
259+
260+
printf("Index %zu ", index);
261+
262+
while (temp) {
263+
264+
printf("-> %d", temp->value);
265+
temp = temp->next;
266+
}
267+
}
268+
269+
void cleanHashTable(HashTable *hashTable) {
270+
if (!hashTable || !hashTable->table) {
271+
fprintf(stderr, "HashTable not initialized");
272+
return;
273+
}
274+
275+
for (size_t i = 0; i < hashTable->size; i++) {
276+
if (hashTable->table[i]) {
277+
Node *temp = hashTable->table[i];
278+
Node *next = NULL;
279+
280+
while (temp) {
281+
next = temp->next;
282+
free(temp);
283+
temp = next;
284+
}
285+
hashTable->table[i] = NULL;
286+
}
287+
}
288+
}
289+
290+
void destroyHashTable(HashTable **hashTable) {
291+
if (!hashTable) {
292+
fprintf(stderr, "HashTable not initialized");
293+
return;
294+
}
295+
296+
HashTable *h = *hashTable;
297+
298+
if (!h) {
299+
*hashTable = NULL;
300+
return;
301+
}
302+
if (!h->table) {
303+
free(h);
304+
*hashTable = NULL;
305+
return;
306+
}
307+
308+
for (size_t i = 0; i < h->size; i++) {
309+
if (h->table[i]) {
310+
Node *temp = h->table[i];
311+
Node *next = NULL;
312+
313+
while (temp) {
314+
next = temp->next;
315+
free(temp);
316+
temp = next;
317+
}
318+
}
319+
}
320+
321+
free(h->table);
322+
free(h);
323+
*hashTable = NULL;
324+
}

0 commit comments

Comments
 (0)