You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
3.7 KiB
201 lines
3.7 KiB
/*
|
|
** C implementation of a hash table ADT
|
|
*/
|
|
typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
|
|
|
|
|
|
typedef struct tagEntry
|
|
{
|
|
char* key;
|
|
char* value;
|
|
} Entry;
|
|
|
|
|
|
|
|
typedef struct tagNode
|
|
{
|
|
Entry* entry;
|
|
|
|
struct tagNode* next;
|
|
} Node;
|
|
|
|
|
|
typedef struct tagHash
|
|
{
|
|
unsigned int table_size;
|
|
|
|
Node** heads;
|
|
|
|
} Hash;
|
|
|
|
|
|
static unsigned int hash_func(const char* str, unsigned int table_size)
|
|
{
|
|
unsigned int hash_value;
|
|
unsigned int a = 127;
|
|
|
|
for (hash_value = 0; *str != 0; ++str)
|
|
hash_value = (a*hash_value + *str) % table_size;
|
|
|
|
return hash_value;
|
|
}
|
|
|
|
|
|
ReturnCode HashCreate(Hash** hash, unsigned int table_size)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (table_size < 1)
|
|
return FAIL;
|
|
|
|
//
|
|
// Allocate space for the Hash
|
|
//
|
|
if (((*hash) = malloc(sizeof(**hash))) == NULL)
|
|
return FAIL;
|
|
|
|
//
|
|
// Allocate space for the array of list heads
|
|
//
|
|
if (((*hash)->heads = malloc(table_size*sizeof(*((*hash)->heads)))) == NULL)
|
|
return FAIL;
|
|
|
|
//
|
|
// Initialize Hash info
|
|
//
|
|
for (i = 0; i < table_size; ++i)
|
|
{
|
|
(*hash)->heads[i] = NULL;
|
|
}
|
|
|
|
(*hash)->table_size = table_size;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
|
|
ReturnCode HashInsert(Hash* hash, const Entry* entry)
|
|
{
|
|
unsigned int index = hash_func(entry->key, hash->table_size);
|
|
Node* temp = hash->heads[index];
|
|
|
|
HashRemove(hash, entry->key);
|
|
|
|
if ((hash->heads[index] = malloc(sizeof(Node))) == NULL)
|
|
return FAIL;
|
|
|
|
hash->heads[index]->entry = malloc(sizeof(Entry));
|
|
hash->heads[index]->entry->key = malloc(strlen(entry->key)+1);
|
|
hash->heads[index]->entry->value = malloc(strlen(entry->value)+1);
|
|
strcpy(hash->heads[index]->entry->key, entry->key);
|
|
strcpy(hash->heads[index]->entry->value, entry->value);
|
|
|
|
hash->heads[index]->next = temp;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
const Entry* HashFind(const Hash* hash, const char* key)
|
|
{
|
|
unsigned int index = hash_func(key, hash->table_size);
|
|
Node* temp = hash->heads[index];
|
|
|
|
while (temp != NULL)
|
|
{
|
|
if (!strcmp(key, temp->entry->key))
|
|
return temp->entry;
|
|
|
|
temp = temp->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ReturnCode HashRemove(Hash* hash, const char* key)
|
|
{
|
|
unsigned int index = hash_func(key, hash->table_size);
|
|
Node* temp1 = hash->heads[index];
|
|
Node* temp2 = temp1;
|
|
|
|
while (temp1 != NULL)
|
|
{
|
|
if (!strcmp(key, temp1->entry->key))
|
|
{
|
|
if (temp1 == hash->heads[index])
|
|
hash->heads[index] = hash->heads[index]->next;
|
|
else
|
|
temp2->next = temp1->next;
|
|
|
|
free(temp1->entry->key);
|
|
free(temp1->entry->value);
|
|
free(temp1->entry);
|
|
free(temp1);
|
|
temp1 = NULL;
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
temp2 = temp1;
|
|
temp1 = temp1->next;
|
|
}
|
|
|
|
return FAIL;
|
|
}
|
|
|
|
|
|
void HashPrint(Hash* hash, void (*PrintFunc)(char*, char*))
|
|
{
|
|
unsigned int i;
|
|
|
|
if (hash == NULL || hash->heads == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < hash->table_size; ++i)
|
|
{
|
|
Node* temp = hash->heads[i];
|
|
|
|
while (temp != NULL)
|
|
{
|
|
PrintFunc(temp->entry->key, temp->entry->value);
|
|
temp = temp->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HashDestroy(Hash* hash)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (hash == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < hash->table_size; ++i)
|
|
{
|
|
Node* temp = hash->heads[i];
|
|
|
|
while (temp != NULL)
|
|
{
|
|
Node* temp2 = temp;
|
|
|
|
free(temp->entry->key);
|
|
free(temp->entry->value);
|
|
free(temp->entry);
|
|
|
|
temp = temp->next;
|
|
|
|
free(temp2);
|
|
}
|
|
}
|
|
|
|
free(hash->heads);
|
|
hash->heads = NULL;
|
|
|
|
free(hash);
|
|
}
|
|
|