forked from justin-lathrop/c
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f54d4c9
commit 9529434
Showing
4 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/* | ||
* @author: jelathro | ||
* @date: 11/2/13 | ||
* | ||
* Implementation file for HashTable. | ||
* | ||
* After ten collisions (ie. ten items in | ||
* a particular hash items list) the hash | ||
* table will expand to the maxCollision | ||
* plus the growthFactor. | ||
*/ | ||
|
||
#include <stdlib.h> | ||
|
||
#include "HashTable.h" | ||
|
||
HashTable * hashtable_initialize(size_t size, size_t mc, size_t gf, hash_function fn, compare_equal efn){ | ||
size_t i; | ||
HashTable * ht = (HashTable *) malloc( sizeof(HashTable) ); | ||
|
||
ht->hf = fn; | ||
ht->eq = efn; | ||
ht->size = size; | ||
ht->maxCollisions = mc; | ||
ht->growthFactor = gf; | ||
|
||
ht->table = (Item **) malloc(size * sizeof( Item * )); | ||
|
||
for(i=0; i<size; i++){ | ||
ht->table[i] = 0; | ||
} | ||
|
||
return(ht); | ||
} | ||
|
||
void * hashtable_get(HashTable * ht, void * key){ | ||
size_t hash = ht->hf(key); | ||
Item * next = ht->table[ hash % ht->size ]; | ||
|
||
while(next){ | ||
if(ht->eq( next->key, key )){ | ||
return( next->value ); | ||
}else{ | ||
next = next->next; | ||
} | ||
} | ||
|
||
return( (void *)0 ); | ||
} | ||
|
||
int hashtable_destroy(HashTable * ht){ | ||
size_t i; | ||
|
||
for(i=0; i<ht->size; i++){ | ||
free(ht->table[i]); | ||
} | ||
|
||
free(ht->table); | ||
free(ht); | ||
|
||
return(1); | ||
} | ||
|
||
int hashtable_resize(HashTable * ht, size_t size){ | ||
HashTable * newht = hashtable_initialize(size, ht->maxCollisions, ht->growthFactor, ht->hf, ht->eq); | ||
int i; | ||
Item * next; | ||
|
||
// Re-enter all the items again into the new hashtable | ||
// with the new size. | ||
for(i=0; i<ht->size; i++){ | ||
if(ht->table[i]){ | ||
for(next=ht->table[i]; next; next=next->next){ | ||
hashtable_add(newht, next->key, next->value); | ||
} | ||
} | ||
|
||
hashtable_remove(ht, ht->table[i]->key); | ||
} | ||
|
||
free(ht->table); | ||
ht->size = newht->size; | ||
ht->table = newht->table; | ||
|
||
return(1); | ||
} | ||
|
||
int hashtable_add(HashTable * ht, void * key, void * value){ | ||
size_t hash = ht->hf(key); | ||
Item * next = ht->table[ hash % ht->size ]; | ||
size_t i = 0; | ||
|
||
while(next){ | ||
// Replace data if key is same | ||
if(ht->eq( next->key, key )){ | ||
next->value = value; | ||
return(1); | ||
} | ||
|
||
next = next->next; | ||
i++; | ||
} | ||
|
||
next = (Item *)malloc( sizeof(Item) ); | ||
next->key = key; | ||
next->value = value; | ||
next->next = ht->table[ hash % ht->size ]; | ||
ht->table[ hash % ht->size ] = next; | ||
|
||
if(i >= ht->maxCollisions){ | ||
hashtable_resize(ht, ht->size + ht->growthFactor); | ||
} | ||
|
||
return(1); | ||
} | ||
|
||
int hashtable_remove(HashTable * ht, void * key){ | ||
size_t hash = ht->hf(key); | ||
Item * next = ht->table[ hash % ht->size ]; | ||
Item * prev = 0; | ||
|
||
while(next){ | ||
if(ht->eq( next->key, key )){ | ||
if(prev){ | ||
prev->next = next->next; | ||
}else{ | ||
ht->table[ hash % ht->size ] = next->next; | ||
} | ||
|
||
free(next); | ||
|
||
return(1); | ||
} | ||
|
||
prev = next; | ||
next = next->next; | ||
} | ||
|
||
return(0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* @author: jelathro | ||
* @date: 11/2/13 | ||
* | ||
* Implementation file for HashTable. | ||
* | ||
* After ten collisions (ie. ten items in | ||
* a particular hash items list) the hash | ||
* table will expand to the maxCollision | ||
* plus the growthFactor. | ||
*/ | ||
|
||
#ifndef __HASHTABLE_H__ | ||
#define __HASHTABLE_H__ | ||
|
||
typedef size_t (* hash_function)(void *); | ||
typedef size_t (* compare_equal)(void *, void *); | ||
|
||
typedef struct Item{ | ||
void * key; | ||
void * value; | ||
struct Item * next; | ||
} Item; | ||
|
||
typedef struct HashTable{ | ||
size_t size; | ||
size_t maxCollisions; | ||
size_t growthFactor; | ||
Item ** table; | ||
hash_function hf; | ||
compare_equal eq; | ||
} HashTable; | ||
|
||
/* | ||
* Creates instance of HashTable with size and | ||
* function given to create a hash of the key. | ||
* | ||
* The hash function is given so that any variable | ||
* or structure etc can be used as the key in the | ||
* key value pairing. | ||
*/ | ||
HashTable * hashtable_initialize(size_t, size_t, int, hash_function, compare_equal); | ||
|
||
/* | ||
* Finds the value in the table in O(n) speed given | ||
* key, and returns value as void * or void * 0 on | ||
* error. | ||
*/ | ||
void * hashtable_get(HashTable *, void *); | ||
|
||
/* | ||
* Free's all memory in the hash table. Returns | ||
* success status 1 true, 0 false. | ||
*/ | ||
int hashtable_destroy(HashTable *); | ||
|
||
/* | ||
* Resizes the hash table to a different | ||
* size. | ||
*/ | ||
int hashtable_resize(HashTable *, size_t); | ||
|
||
/* | ||
* Adds a new key value pair to the table. If | ||
* key already exists it will overwrite it. | ||
*/ | ||
int hashtable_add(HashTable *, void *, void *); | ||
|
||
/* | ||
* Free's and deletes memory of a item and clears | ||
* the spot in the table. | ||
*/ | ||
int hashtable_remove(HashTable *, void *); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<h1>HashTable</h1> | ||
<hr /> | ||
|
||
|
||
A pure C way to make a hash table to hold generic data and use a generic key. | ||
|
||
|
||
The example use of the hashtable is simple but is to show the resizing capability | ||
within the hashtable. Every hashtable is O(n) on lookups, but this is with optimal | ||
hardware and minimal to no collisions. So we have a hashtable that can start at a | ||
small size and when added elements to it, it can expand to hold them with less | ||
collisions. | ||
|
||
|
||
Configural parameters in the hashtable: | ||
<ul> | ||
<li><b>Starting size:</b> Size the table will start at.</li> | ||
<li><b>Values to hold:</b> Cast every value inserted into the hashtable as void * and you | ||
can use any value under the sun.</li> | ||
<li><b>Key to search with:</b> Key to do hashes on and search with. Can be anything becuase | ||
the user needs to define a hash function for the hashtable returning the hash to use.</li> | ||
<li><b>Max collisions:</b> Max number of collisions before table will resize to keep it | ||
at an optimal size for quickest lookups.</li> | ||
<li><b>Growth factor:</b> The amount of entries to add onto the size if the max number | ||
of collisions happen. If the size of the table is large then the amount of time a | ||
resize can take can be a little while.. but worth it in most cases.</li> | ||
</ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* @author: jelathro | ||
* @date: 11/2/13 | ||
* | ||
* Test/example use/use case | ||
* for HashTable implementation. | ||
*/ | ||
|
||
#include <stdio.h> | ||
|
||
#include "HashTable.h" | ||
|
||
size_t hash(void * key){ | ||
size_t hash = 0; | ||
const char * k = (const char *)key; | ||
|
||
while (*k) { | ||
hash = hash*37 + *k++; | ||
} | ||
return hash; | ||
} | ||
|
||
size_t mycompare_equal(void * key1, void * key2){ | ||
if((const char *)key1 == (const char *)key2) | ||
return(1); | ||
else | ||
return(0); | ||
} | ||
|
||
int main(int argc, char ** argv){ | ||
HashTable * ht = hashtable_initialize(1, 1, 2, hash, mycompare_equal); | ||
|
||
hashtable_add(ht, (void *)"1", (void *)"ONE"); | ||
hashtable_add(ht, (void *)"2", (void *)"TWO"); | ||
hashtable_add(ht, (void *)"3", (void *)"THREE"); | ||
hashtable_add(ht, (void *)"4", (void *)"FOUR"); | ||
|
||
printf("ht[\"1\"]: %s\n", (const char *)hashtable_get(ht, (void *)"1")); | ||
printf("ht[\"2\"]: %s\n", (const char *)hashtable_get(ht, (void *)"2")); | ||
printf("ht[\"3\"]: %s\n", (const char *)hashtable_get(ht, (void *)"3")); | ||
printf("ht[\"4\"]: %s\n", (const char *)hashtable_get(ht, (void *)"4")); | ||
|
||
// Add more to inact resize | ||
|
||
hashtable_add(ht, (void *)"5", (void *)"FIVE"); | ||
hashtable_add(ht, (void *)"6", (void *)"SIX"); | ||
hashtable_add(ht, (void *)"7", (void *)"SEVEN"); | ||
hashtable_add(ht, (void *)"8", (void *)"EIGHT"); | ||
|
||
printf("ht[\"5\"]: %s\n", (const char *)hashtable_get(ht, (void *)"5")); | ||
printf("ht[\"6\"]: %s\n", (const char *)hashtable_get(ht, (void *)"6")); | ||
printf("ht[\"7\"]: %s\n", (const char *)hashtable_get(ht, (void *)"7")); | ||
printf("ht[\"8\"]: %s\n", (const char *)hashtable_get(ht, (void *)"8")); | ||
|
||
hashtable_destroy(ht); | ||
|
||
return(0); | ||
} |