#ifndef HEADER_H_INCLUDED #define HEADER_H_INCLUDED #include #include #include typedef struct hashentry__s { char songtitle[256], interpreter[256]; } hashentry_t; typedef struct hasharray__s { hashentry_t *entries; long num_entries; } hasharray_t; typedef struct hashcontainer__s { hasharray_t *harrays; long hashsize; } hashcontainer_t; long hash_key(char songtitle[], char interpreter[], long hash_max); hashcontainer_t *create_hash(long hashsize); void delete_hash(hashcontainer_t *hashcontainer); void insert_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]); hashentry_t *search_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]); void delete_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]); void print_hash(hashcontainer_t *hashcontainer); long count_entries(hashcontainer_t *hashcontainer); long count_entries_with_songtitle(hashcontainer_t *hashcontainer, char songtitle[]); void insert_entry_ext_exp(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[], long(*hashkey_gen)(hashentry_t *entry, long hash_max)); void insert_entry_ext(hashcontainer_t *hashcontainer, hashentry_t *hashentry, long(*hashkey_gen)(hashentry_t *entry, long hash_max)); long hashkey_gen1(hashentry_t *entry, long hash_max); long hashkey_gen2(hashentry_t *entry, long hash_max); void rehash1(hashcontainer_t *hashcontainer, long(*hashkey_gen)(hashentry_t *entry, long hash_max), long hash_max); void rehash2(hashcontainer_t *hashcontainer, long(*hashkey_gen)(hashentry_t *entry, long hash_max), long hash_max); #endif // HEADER_H_INCLUDED #include "header.h" long hash_key(char songtitle[], char interpreter[], long hash_max) { unsigned long i, index = 0; for (i = 0; i < strlen(songtitle); ++i) index = 64 * index + (long)(songtitle[i]); for (i = 0; i < strlen(interpreter); ++i) index = 64 * index + (long)(interpreter[i]); return index % hash_max; } long hashkey_gen1(hashentry_t *entry, long hash_max) { unsigned long i, index = 0; for (i = 0; i < strlen(entry->songtitle); ++i) index = 64 * index + (long)(entry->songtitle[i]); for (i = 0; i < strlen(entry->interpreter); ++i) index = 64 * index + (long)(entry->interpreter[i]); return index % hash_max; } hashcontainer_t *create_hash(long hashsize) { unsigned long i; hashcontainer_t *new = 0; if (!(new = malloc(sizeof(hashcontainer_t)))) { fprintf(stderr, "Memory allocation error in create_hash()"); exit(-1); } if (!(new->harrays = calloc(hashsize, sizeof(hasharray_t)))) { fprintf(stderr, "Memory allocation error in create_hash()"); exit(-1); } new->hashsize = hashsize; for (i = 0; i < hashsize; i++) { new->harrays[i]; } return new; } void delete_hash(hashcontainer_t *hashcontainer) { unsigned long i; for (i = 0; i < hashcontainer->hashsize; i++) { if (hashcontainer->harrays[i].entries) { free(hashcontainer->harrays[i].entries); hashcontainer->harrays[i].entries = 0; hashcontainer->harrays[i].num_entries = 0; } } free(hashcontainer->harrays); hashcontainer->harrays = 0; hashcontainer->hashsize = 0; } void insert_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]) { unsigned long index = hash_key(songtitle, interpreter, hashcontainer->hashsize); hashcontainer->harrays[index].num_entries++; hashcontainer->harrays[index].entries = realloc(hashcontainer->harrays[index].entries, hashcontainer->harrays[index].num_entries * sizeof(hashentry_t)); strcpy(hashcontainer->harrays[index].entries[hashcontainer->harrays[index].num_entries - 1].songtitle, songtitle); strcpy(hashcontainer->harrays[index].entries[hashcontainer->harrays[index].num_entries - 1].interpreter, interpreter); } hashentry_t *search_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]) { unsigned long index = hash_key(songtitle, interpreter, hashcontainer->hashsize); unsigned long len = hashcontainer->harrays[index].num_entries, i; for (i = 0; i < len; i++) { if ((strcmp(hashcontainer->harrays[index].entries[i].interpreter, interpreter) == 0) && (strcmp(hashcontainer->harrays[index].entries[i].songtitle, songtitle) == 0)) return (hashcontainer->harrays[index].entries)+i; } return 0; } void delete_entry(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[]) { unsigned long index = hash_key(songtitle, interpreter, hashcontainer->hashsize); unsigned long len = hashcontainer->harrays[index].num_entries, i; for (i = 0; i < len; i++) { if ((strcmp(hashcontainer->harrays[index].entries[i].interpreter, interpreter) == 0) && (strcmp(hashcontainer->harrays[index].entries[i].songtitle, songtitle) == 0)) { if (i == 0 && len == 1) { free(hashcontainer->harrays[index].entries); hashcontainer->harrays[index].entries = 0; hashcontainer->harrays[index].num_entries = 0; } else { if (i != len - 1) memcpy(hashcontainer->harrays[index].entries + i, hashcontainer->harrays[index].entries + i + 1, (len - i - 1)* sizeof(hashentry_t)); hashcontainer->harrays[index].entries = realloc(hashcontainer->harrays[index].entries, --hashcontainer->harrays[index].num_entries * sizeof(hashentry_t)); } } } } void print_hash(hashcontainer_t *hashcontainer) { unsigned long i, j; for (i = 0; i < hashcontainer->hashsize; i++) { fprintf(stdout, "Hash index %ld\n", i); for (j = 0; j < hashcontainer->harrays[i].num_entries; j++) { fprintf(stdout, "%s\t%s\n", hashcontainer->harrays[i].entries[j].songtitle, hashcontainer->harrays[i].entries[j].interpreter); } fprintf(stdout, "\n"); } } long count_entries(hashcontainer_t *hashcontainer) { unsigned long i, j, count = 0; for (i = 0; i < hashcontainer->hashsize; i++) { for (j = 0; j < hashcontainer->harrays[i].num_entries; j++) { count++; } } return count; } long count_entries_with_songtitle(hashcontainer_t *hashcontainer, char songtitle[]) { unsigned long i, j, count = 0; for (i = 0; i < hashcontainer->hashsize; i++) { for (j = 0; j < hashcontainer->harrays[i].num_entries; j++) { if (strcmp(hashcontainer->harrays[i].entries[j].songtitle, songtitle) == 0) count++; } } return count; } void insert_entry_ext_exp(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[], long(*hashkey_gen)(hashentry_t *entry, long hash_max)) { hashentry_t *new = malloc(sizeof(hashentry_t)); strcpy(new->songtitle, songtitle); strcpy(new->interpreter, interpreter); unsigned long index = hashkey_gen(new, hashcontainer->hashsize); hashcontainer->harrays[index].num_entries++; hashcontainer->harrays[index].entries = realloc(hashcontainer->harrays[index].entries, hashcontainer->harrays[index].num_entries * sizeof(hashentry_t)); memcpy(hashcontainer->harrays[index].entries + hashcontainer->harrays[index].num_entries - 1, new, sizeof(hashentry_t)); } void insert_entry_ext(hashcontainer_t *hashcontainer, hashentry_t *new, long(*hashkey_gen)(hashentry_t *entry, long hash_max)) { unsigned long index = hashkey_gen(new, hashcontainer->hashsize); hashcontainer->harrays[index].num_entries++; hashcontainer->harrays[index].entries = realloc(hashcontainer->harrays[index].entries, hashcontainer->harrays[index].num_entries * sizeof(hashentry_t)); memcpy(hashcontainer->harrays[index].entries + hashcontainer->harrays[index].num_entries - 1, new, sizeof(hashentry_t)); } hashentry_t *search_entry_ext(hashcontainer_t *hashcontainer, char songtitle[], char interpreter[], long(*hashkey_gen)(hashentry_t *entry, long hash_max)) { hashentry_t *new = malloc(sizeof(hashentry_t)); strcpy(new->songtitle, songtitle); strcpy(new->interpreter, interpreter); unsigned long index = hashkey_gen(new, hashcontainer->hashsize); unsigned long i; for (i = 0; i < hashcontainer->harrays[index].num_entries; i++) { if ((strcmp(hashcontainer->harrays[index].entries[i].interpreter, interpreter) == 0) && (strcmp(hashcontainer->harrays[index].entries[i].songtitle, songtitle) == 0)) return (hashcontainer->harrays[index].entries)+i; } return 0; } void rehash1(hashcontainer_t *hashcontainer, long(*hashkey_gen)(hashentry_t *entry, long hash_max), long hash_max) { hashcontainer_t *new = create_hash(hash_max); unsigned long i, j; for (i = 0; i < hashcontainer->hashsize; i++) { for (j = 0; j < hashcontainer->harrays[i].num_entries; j++) { insert_entry_ext(new, hashcontainer->harrays[i].entries + j, hashkey_gen); } } delete_hash(hashcontainer); hashcontainer->harrays = new->harrays; hashcontainer->hashsize = new->hashsize; } void rehash2(hashcontainer_t *hashcontainer, long(*hashkey_gen)(hashentry_t *entry, long hash_max), long hash_max) { unsigned long i, j, count = 0, len = count_entries(hashcontainer); hashentry_t temp[len]; for (i = 0; i < hashcontainer->hashsize; i++) { for (j = 0; j < hashcontainer->harrays[i].num_entries; j++) { strcpy(temp[count].songtitle, hashcontainer->harrays[i].entries[j].songtitle); strcpy(temp[count].interpreter, hashcontainer->harrays[i].entries[j].interpreter); count++; } } delete_hash(hashcontainer); hashcontainer_t *new = create_hash(hash_max); for (i = 0; i < len; i++) { insert_entry_ext(new, &temp[i], hashkey_gen); } hashcontainer->harrays = new->harrays; hashcontainer->hashsize = new->hashsize; free(new); } #include "source.c" int main() { hashcontainer_t *container = create_hash(3); insert_entry_ext_exp(container, "Title1", "Inter1", hashkey_gen1); insert_entry_ext_exp(container, "Title2", "Inter2", hashkey_gen1); insert_entry_ext_exp(container, "Title2", "Inter2", hashkey_gen1); insert_entry_ext_exp(container, "Title3", "Inter3", hashkey_gen1); insert_entry_ext_exp(container, "Title3", "Inter3", hashkey_gen1); insert_entry_ext_exp(container, "Title3", "Inter3", hashkey_gen1); insert_entry_ext_exp(container, "Title3", "Inter3", hashkey_gen1); insert_entry_ext_exp(container, "Title4", "Inter4", hashkey_gen1); insert_entry_ext_exp(container, "Title7", "Inter7", hashkey_gen1); insert_entry_ext_exp(container, "Title7", "Inter7", hashkey_gen1); delete_entry(container, "Title7", "Inter7"); print_hash(container); fprintf(stdout, "\nRehashing...\n\n"); rehash1(container, hashkey_gen1, 11); print_hash(container); hashentry_t *temp = search_entry_ext(container, "Title7", "Inter7", hashkey_gen1); if (temp) fprintf(stdout, "%s\t%s\n", temp->songtitle, temp->interpreter); else fprintf(stdout, "Not found.\n"); fprintf(stdout, "%ld entries found.", count_entries(container)); delete_hash(container); free(container); return 0; }