cs240/hw/hw10/hashtable.c
2018-10-15 17:20:57 -04:00

195 lines
4.1 KiB
C
Executable File

#include <stdlib.h>
#include <string.h>
#include "hashtable.h"
static hashtable_ent_t* add_new(hashtable_ent_t** entry, const char* key) {
if (entry == NULL || key == NULL) return NULL;
*entry = (hashtable_ent_t*)malloc(sizeof(hashtable_ent_t));
if (*entry == NULL) return NULL;
(*entry)->key = strdup(key);
if ((*entry)->key == NULL) {
free(*entry);
return NULL;
}
(*entry)->next = NULL;
return *entry;
}
/*
* Helper function that does most of the implemention work
*/
static hashtable_ent_t* locate(hashtable_t* ht, const char* key, int create_if_missing) {
if (ht == NULL || key == NULL) return NULL;
int h = hash(key) % ht->table_len;
hashtable_ent_t* node = ht->table[h];
if (node != NULL) {
/* Search until we find a match or hit the end */
while (node->next != NULL && strcmp(key, node->key)) node = node->next;
if (!strcmp(key, node->key)) {
return node;
} else if (node->next == NULL && create_if_missing) {
/* If we failed to find the key, we can create an entry in place */
return add_new(&node->next, key);
}
} else if (create_if_missing) {
return add_new(&ht->table[h], key);
}
return NULL;
}
hashtable_t *create_hashtable(int max_size) {
if (max_size <= 0) {
return NULL;
}
hashtable_t* ht = (hashtable_t *) malloc(sizeof(hashtable_t));
ht->table = (hashtable_ent_t **) malloc(sizeof(hashtable_ent_t) * max_size);
ht->table_len = max_size;
for (int i = 0; i < max_size; i++) {
ht->table[i] = NULL;
}
return ht;
}
void free_hashtable(hashtable_t *ht) {
if (ht == NULL) {
return;
}
for (int i = 0; i < ht->table_len; i++) {
hashtable_ent_t* node = ht->table[i];
while (node != NULL) {
hashtable_ent_t* next = node->next;
free(node->key);
node->key = NULL;
free(node);
node = next;
}
}
free(ht->table);
ht->table = NULL;
free(ht);
ht = NULL;
}
int get(hashtable_t *ht, const char *key, double *value) {
if (ht == NULL || key == NULL || value == NULL) {
return -1;
}
hashtable_ent_t* entry = locate(ht, key, 0);
if (entry != NULL) {
*value = entry->value;
return 0;
}
return -1;
/*hashtable_ent_t* entry = ht->table[hash(key) % ht->table_len];
while (entry != NULL && entry->key != NULL) {
if (strcmp(entry->key, key) == 0) {
*value = entry->value;
return 0;
}
entry = entry->next;
}
return -1;*/
}
int set(hashtable_t *ht, const char *key, double value) {
if (ht == NULL || key == NULL) {
return -1;
}
hashtable_ent_t* entry = locate(ht, key, 1);
if (entry == NULL)
return -1;
entry->value = value;
return 0;
/*hashtable_ent_t* entry = ht->table[hash(key) % ht->table_len];
while (entry != NULL && entry->key != NULL) {
if (strcmp(entry->key, key) == 0) {
entry->value = value;
return 0;
}
entry = entry->next;
}
// Does not exist. Add a new entry.
hashtable_ent_t* newEntry = (hashtable_ent_t *) malloc(sizeof(hashtable_ent_t));
if (newEntry == NULL) {
return -1; // Out of memory.
}
newEntry->key = strdup(key);
newEntry->value = value;
entry->next = newEntry;
newEntry->next = NULL;
return 0;*/
}
int key_exists(hashtable_t *ht, const char *key) {
if (ht == NULL || key == NULL)
return -1;
hashtable_ent_t* entry = locate(ht, key, 0);
if (entry != NULL)
return 1;
return 0;
/*double* val = (double *) malloc(sizeof(double));
int result = get(ht, key, val);
free(val);
if (result == 0)
return 1;
else
return 0;*/
}
int remove_key(hashtable_t *ht, const char *key) {
if (ht == NULL || key == NULL || !key_exists(ht, key))
return -1;
int i = hash(key) % ht->table_len;
hashtable_ent_t* entry = ht->table[i];
hashtable_ent_t* prev = NULL;
while (entry != NULL && entry->key != NULL) {
if (strcmp(entry->key, key) == 0) {
if (prev == NULL) { // First node (head).
ht->table[i] = entry->next; // If next is null, THAT'S OKAY!
} else {
prev->next = entry->next; // Again, it's okay if next is null.
}
free(entry->key);
entry->key = NULL;
free(entry);
entry = NULL;
return 0;
}
prev = entry;
entry = entry->next;
}
return -1;
}