Adding hash map and radix sort.

This commit is contained in:
Martin Dvorak 2013-12-15 01:03:02 +01:00
parent 273c8456e2
commit 6b8d1564bc
4 changed files with 224 additions and 0 deletions

67
src/hashmap.c Normal file
View file

@ -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 );
}

27
src/include/hashmap.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef _HASHMAP_H_
#define _HASHMAP_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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_ */

23
src/include/radixsort.h Normal file
View file

@ -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_ */

107
src/radixsort.c Normal file
View file

@ -0,0 +1,107 @@
#include "include/radixsort.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stddef.h>
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
}