Update to use HashMap with chaining, cli args, and freeing all memory (no leaks).

This commit is contained in:
Jesse Brault 2025-02-11 17:19:23 -06:00
parent 2956811807
commit a8bcc6899c
3 changed files with 104 additions and 57 deletions

View File

@ -3,3 +3,6 @@ twoSum: runTwoSum.c twoSum.c
run: twoSum run: twoSum
./twoSum ./twoSum
valgrind: twoSum
valgrind --leak-check=full ./twoSum -t 3 1 2

View File

@ -1,26 +1,40 @@
#include "./twoSum.c" #include "./twoSum.c"
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
int main() { #define USAGE "Usage: twoSum -t <target> <e0> <e1> [...<es>]\n"
int nums[] = { 0, 4, 3, 0 };
int returnSize = 0; int main(int argc, char *argv[]) {
int *result = twoSum(nums, 4, 0, &returnSize); if (argc < 5) {
bool foundFirst, foundSecond; fprintf(stderr, USAGE);
for (int i = 0; i < returnSize; i++) {
switch (result[i]) {
case 0:
foundFirst = true;
break;
case 3:
foundSecond = true;
break;
}
}
if (foundFirst && foundSecond) {
return 0;
} else {
fprintf(stderr, "Did not find indices [0, 1]\n");
return 1; return 1;
} }
if (strcmp("-t", argv[1]) != 0) {
fprintf(stderr, USAGE);
return 1;
}
int target = atoi(argv[2]);
int *nums = malloc(sizeof(int) * (argc - 3));
for (int i = 3; i < argc; i++) {
nums[i - 3] = atoi(argv[i]);
}
int returnSize = 0;
int *result = twoSum(nums, argc - 3, target, &returnSize);
if (!returnSize) {
fprintf(stderr, "Did not find two indices.");
return 1;
}
for (int i = 0; i < returnSize; i++) {
printf("%i ", result[i]);
}
printf("\n");
free(result);
free(nums);
return 0;
} }

View File

@ -4,15 +4,20 @@ typedef struct {
int key, value; int key, value;
} HashMapEntry; } HashMapEntry;
typedef struct EntryList {
HashMapEntry *entry;
struct EntryList *next;
} EntryList;
typedef struct { typedef struct {
int size; int size;
HashMapEntry **entries; EntryList **entries;
} HashMap; } HashMap;
HashMap *makeHashMap(int size) { HashMap *makeHashMap(int size) {
HashMap *m = malloc(sizeof(HashMap)); HashMap *m = malloc(sizeof(HashMap));
m->size = size; m->size = size;
m->entries = malloc(size * sizeof(HashMapEntry*)); m->entries = malloc(size * sizeof(EntryList *));
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
m->entries[i] = NULL; m->entries[i] = NULL;
} }
@ -30,48 +35,72 @@ HashMapEntry *makeEntry(int key, int value) {
return e; return e;
} }
#define PUT_SUCCESS 1 EntryList *makeLinkedList(HashMapEntry *e) {
#define PUT_FAIL 0 EntryList *l = malloc(sizeof(EntryList));
l->entry = e;
int putAt(HashMap *m, HashMapEntry *e, int index) { l->next = NULL;
if (m->entries[index] == NULL) { return l;
m->entries[index] = e;
return PUT_SUCCESS;
}
return PUT_FAIL;
} }
int put(HashMap *m, int key, int value) { void appendEntryList(EntryList *l, HashMapEntry *e) {
while (l->next != NULL)
l = l->next;
l->next = makeLinkedList(e);
}
void putAt(HashMap *m, HashMapEntry *e, int index) {
if (m->entries[index] == NULL) {
m->entries[index] = makeLinkedList(e);
} else {
appendEntryList(m->entries[index], e);
}
}
void put(HashMap *m, int key, int value) {
int hash = hashCode(m, key); int hash = hashCode(m, key);
HashMapEntry *e = makeEntry(key, value); HashMapEntry *e = makeEntry(key, value);
for (int i = hash; i < m->size; i++) { putAt(m, e, hash);
if (putAt(m, e, i)) return PUT_SUCCESS;
}
for (int i = 0; i < hash; i++) {
if (putAt(m, e,i)) return PUT_SUCCESS;
}
return PUT_FAIL;
} }
HashMapEntry *get(HashMap *m, int key) { HashMapEntry *get(HashMap *m, int key) {
int hash = hashCode(m, key); int hash = hashCode(m, key);
for (int i = hash; i < m->size; i++) { EntryList *l = m->entries[hash];
if (m->entries[i] != NULL) { while (l != NULL && l->entry->key != key) {
HashMapEntry *e = m->entries[i]; l = l->next;
if (e->key == key) {
return e;
}
}
} }
for (int i = 0; i < hash; i++) { if (l == NULL) return NULL;
if (m->entries[i] != NULL) { return l->entry;
HashMapEntry *e = m->entries[i]; }
if (e->key == key) {
return e; void freeEntryList(EntryList *l) {
} int size = 0;
} EntryList *current = l;
while (current != NULL) {
current = current->next;
size++;
} }
return NULL;
EntryList **reversed = malloc(size * sizeof(EntryList *));
current = l;
for (int i = 0; i < size; i++) {
reversed[size - i - 1] = current;
current = current->next;
}
for (int i = 0; i < size; i++) {
free(reversed[i]->entry);
free(reversed[i]);
}
free(reversed);
}
void freeHashMap(HashMap *m) {
for (int i = 0; i < m->size; i++) {
freeEntryList(m->entries[i]);
}
free(m->entries);
free(m);
} }
/** /**
@ -87,12 +116,13 @@ int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
result[0] = i; result[0] = i;
result[1] = e->value; result[1] = e->value;
*returnSize = 2; *returnSize = 2;
freeHashMap(m);
return result; return result;
} else if (!put(m, nums[i], i)) { } else {
*returnSize = 0; put(m, nums[i], i);
return malloc(0); // fail
} }
} }
freeHashMap(m);
*returnSize = 0; *returnSize = 0;
return malloc(0); return malloc(0);
} }