From 6b8d1564bcab7d8a3ca3278844d341b3d2977f09 Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Sun, 15 Dec 2013 01:03:02 +0100 Subject: [PATCH] Adding hash map and radix sort. --- src/hashmap.c | 67 +++++++++++++++++++++++++ src/include/hashmap.h | 27 ++++++++++ src/include/radixsort.h | 23 +++++++++ src/radixsort.c | 107 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 224 insertions(+) create mode 100644 src/hashmap.c create mode 100644 src/include/hashmap.h create mode 100644 src/include/radixsort.h create mode 100644 src/radixsort.c diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 0000000..060751c --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,67 @@ +#include "include/hashmap.h" + +unsigned int hashmap_hash( const char *str ) { + int i; + unsigned int result = 0; + + for( i = 0; str[ i ] != '\0'; i++ ) + result = result * 31 + str[ i ]; + + return result % HASH_MAP_SIZE; +} + +void hashmap_init( HashMap * hs ) { + int i; + hs->currentSize = 0; + for( i = 0; i < HASH_MAP_SIZE; i++ ) { + hs->lists[ i ] = NULL; + } +} + +void *hashmap_get( const HashMap * hs, const char *key ) { + int listNum = hashmap_hash( key ); + struct HashMapNode *ptr = hs->lists[ listNum ]; + + while( ptr != NULL && strcmp( ptr->key, key ) != 0 ) + ptr = ptr->next; + + return (ptr != NULL? ptr->value : NULL); +} + +int hashmap_put( HashMap * hs, const char *key, void *value) { + struct HashMapNode *newNode; + int listNum; + + if( hashmap_get( hs, key ) ) + return 0; + + listNum = hashmap_hash( key ); + + + newNode = (struct HashMapNode *) malloc( sizeof ( struct HashMapNode ) ); + if( newNode == NULL ) { + fprintf( stderr, "Error allocating node" ); + return 0; + } + + newNode->key = strdup( key ); + newNode->value = value; + newNode->next = hs->lists[ listNum ]; + hs->lists[ listNum ] = newNode; + hs->currentSize++; + + return 1; +} + +int hashmap_size(const HashMap * hs) { + return hs->currentSize; +} + +void hashmap_print( const HashMap * hs ) { + int i; + struct HashMapNode *ptr; + + for( i = 0; i < HASH_MAP_SIZE; i++ ) + for( ptr = hs->lists[ i ]; ptr != NULL; ptr = ptr->next ) + printf( "%s\n", ptr->key ); +} diff --git a/src/include/hashmap.h b/src/include/hashmap.h new file mode 100644 index 0000000..28b9eaa --- /dev/null +++ b/src/include/hashmap.h @@ -0,0 +1,27 @@ +#ifndef _HASHMAP_H_ +#define _HASHMAP_H_ + +#include +#include +#include + +#define HASH_MAP_SIZE 10007 + +struct HashMapNode { + char *key; + void *value; + struct HashMapNode *next; +}; + +typedef struct { + struct HashMapNode * lists[HASH_MAP_SIZE]; + int currentSize; +} HashMap; + +void hashmap_init( HashMap *hm ); +void *hashmap_get( const HashMap *hm, const char *key ); +int hashmap_put( HashMap *hm, const char *key, void *value ); +int hashmap_size( const HashMap *hm ); +void hashmap_print( const HashMap *hm ); + +#endif /* HASHMAP_H_ */ diff --git a/src/include/radixsort.h b/src/include/radixsort.h new file mode 100644 index 0000000..c2a87ae --- /dev/null +++ b/src/include/radixsort.h @@ -0,0 +1,23 @@ +#ifndef RADIXSORT_H_ +#define RADIXSORT_H_ + +typedef struct radixitem { + unsigned key; + void *data; + struct radixitem *next; +} RadixItem; + +#define SIX2FOUR_SIZE 1000 + +typedef struct { + unsigned size; + unsigned maxValue; + RadixItem **six2four[SIX2FOUR_SIZE]; +} RadixSorter; + +void radixsort_init(RadixSorter *rs); +void radixsort_add(RadixSorter *rs, RadixItem *item); +RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data); +RadixItem **radixsort_dump(RadixSorter *rs); + +#endif /* RADIXSORT_H_ */ diff --git a/src/radixsort.c b/src/radixsort.c new file mode 100644 index 0000000..e64d060 --- /dev/null +++ b/src/radixsort.c @@ -0,0 +1,107 @@ +#include "include/radixsort.h" +#include +#include +#include +#include +#include + +RadixItem **radixsort_get_slot() { + RadixItem **slot=malloc(SIX2FOUR_SIZE * sizeof(RadixItem*)); + memset(slot, 0, SIX2FOUR_SIZE * sizeof(RadixItem*)); + return slot; +} + +void radixsort_init(RadixSorter *rs) { + rs->size=0; + memset(rs->six2four, 0, SIX2FOUR_SIZE * sizeof(RadixItem*)); + rs->maxValue=0; +} + +void radixsort_add(RadixSorter *rs, RadixItem *item) { + double d = ((double) item->key)/1000.0; + unsigned six2four = (unsigned)trunc(d); + unsigned three2zero=item->key-six2four*1000; + + if(rs->six2four[six2four]==NULL) { + rs->six2four[six2four]=radixsort_get_slot(); + } + + RadixItem *chain=rs->six2four[six2four][three2zero]; + rs->six2four[six2four][three2zero]=item; + if(chain==NULL) { + item->next=NULL; + } else { + item->next=chain; + } + + rs->size++; + rs->maxValue=(rs->maxValue>item->key?rs->maxValue:item->key); +} + +RadixItem **radixsort_dump(RadixSorter *rs) { + if(rs->size>0) { + RadixItem **result=malloc(rs->size * sizeof(RadixItem *)); + double d = ((double)rs->maxValue)/1000.0; + int six2four = (int)trunc(d); + + int s, t, i=0; + s=six2four; + do { + t=SIX2FOUR_SIZE-1; + do { + if(rs->six2four[s]!=NULL) { + if(rs->six2four[s][t]!=NULL) { + result[i++]=rs->six2four[s][t]; + + RadixItem *ri=rs->six2four[s][t]->next; + while(ri) { + result[i++]=ri; + ri=ri->next; + } + } + } + } while(--t>=0); + } while(--s>=0); + return result; + } + + return NULL; +} + +RadixItem *radix_cut(RadixSorter *rs, unsigned key, void *data) { + if(key<=rs->maxValue) { + double d = ((double) key)/1000.0; + unsigned six2four = (unsigned)trunc(d); + unsigned three2zero=key-six2four*1000; + + if(rs->six2four[six2four]) { + RadixItem *ri=rs->six2four[six2four][three2zero]; + RadixItem *lastRi=NULL; + while(ri->data!=data) { + if(ri->next) { + lastRi=ri; + ri=ri->next; + } else { + break; + } + } + if(ri->data==data) { + if(lastRi) { + lastRi->next=ri->next; + } else { + rs->six2four[six2four][three2zero]=ri->next; + } + ri->next=NULL; + rs->size--; + return ri; + } + } + } + return NULL; +} + +void radixsort_destroy(RadixSorter *rs) { + // TODO destroy RadixItems chains + // TODO destroy three2one segments + // TODO destroy six2four +}