#include
#include
#include
#include "GenericHashTable.h"
#define STR_TYPE 1
{
void* data;
struct Object* nextObj;
}Object;
typedef struct Table {
Object** arr;
int
int listLen;
int originalSize;
int ratio;
int currentSize;
int timesDup; //
}Table;
/**
* The function gets the original size,
table->arr = (Object **)realloc(table->arr, table->currentSize * 2 * sizeof(Object *)); // Reallocate
if(table->arr == NULL)
{
printf("Error occured while duplicating the array. \n");
return;
}
table->currentSize = table->currentSize * 2; // Update the size.
table->ratio = table->currentSize / table->originalSize; // Update the rate of currentSize/originalSize.
for (int i = prev_size; i < table->currentSize; i++) // Initialize new cells
{
table->arr[i] = NULL;
}
for (int i = table->currentSize - 1; i > 0; i--) // Loop to move all old
{
if (table->arr[i] != NULL)
{
table->arr[2 * i] = table->arr[i];
table->arr[i] = NULL; // Initialize old index.
}
}
}
int listLength(Object *obj)
{
int count = 1;
if (obj == NULL)
return 0;
while (obj->nextObj != NULL)
{
count++;
obj = obj->nextObj;
}
return count;
}
int intHashFun(int *key, int origSize)
{
int toReturn = 0;
toReturn = *key % origSize;
return toReturn;
}
int strHashFun(char *key, int origSize)
{
int ascii_val = 0;
int toReturn = 0;
for (int i = 0; i < strlen(key); key++)
{
ascii_val += key[i];
}
toReturn = ascii_val % origSize;
return toReturn;
}
Object *createObject(void *data)
{
Object *new_obj = (Object *)calloc(1, sizeof(Object)); // Allocate
if (new_obj == NULL)
{
printf("An error occured creating an object. \n");
return NULL;
}
new_obj->data = data;
if (new_obj->data == NULL)
{
printf("An error occured creating an object. \n");
return NULL;
}
else
{
new_obj->nextObj = NULL;
return new_obj;
}
}
* it initializes the Table
{
Table *new_table = (Table *)calloc(1, sizeof(Table)); // Allocate memory for
* On success, the
if (new_table == NULL)
{
printf("An error occured while allocating the table.\n");
return NULL;
}
//------Variables Initialization--------///
new_table->listLen = listLength;
new_table->dataType = dType;
new_table->originalSize = size;
new_table->ratio = 1;
new_table->currentSize = size;
new_table->arr = (Object **)calloc(size, sizeof(Object *));
if (new_table->arr == NULL)
{
printf("An error occured while allocating the table.\n");
return NULL;
}
else
{
return new_table;
}
}
void printTable(Table *table)
{
Object *current_object;
int data_int = 0;
char *data_string = NULL;
if (table->dataType == INT_TYPE)
{
for (int i = 0; i < table->currentSize; i++)
{
printf("[%d]: \t", i);
current_object = table->arr[i];
while (current_object != NULL)
{
data_int = *((int *)(current_object->data));
if (current_object->nextObj == NULL)
{
printf("%d", data_int);
}
else
printf("%d \t --> \t", data_int);
current_object = current_object->nextObj;
}
printf("\n");
}
printf("--------------------------------------------------\n");
}
else if (table->dataType == STR_TYPE)
{
for (int i = 0; i < table->currentSize; i++)
{
printf("[%d]: \t", i);
current_object = table->arr[i];
while (current_object != NULL)
{
data_string = (char *)current_object->data;
if (current_object->nextObj == NULL)
{
printf("%s", data_string);
}
else
printf("%s \t --> \t", data_string);
current_object = current_object->nextObj;
}
printf("\n");
}
printf("--------------------------------------------------\n");
}
}
int add(Table *table, void *data)
{
int location = -1; // A variable to save the location of the hash value.
int *data_int; // A pointer in-case the data-type is integer.
char *data_str; // A pointer in-case the data-type is string.
Object *current_object; // A pointer to the current object.
Object *new_object; // A
if (table->dataType == INT_TYPE) // In-case the data-type is integer, allocate memory for data_int, and calculate the hash value.
{
data_int = (int *)calloc(1, sizeof(int));
if (data_int == NULL)
{
printf("Error: failure in memory allocation.\n");
return -1;
}
*data_int = *((int *)(data));
location = table->ratio * intHashFun(data_int, table->originalSize);
}
else if (table->dataType == STR_TYPE) // In-case the data-type is string, allocate memory for data_str, and calculate the hash value.
{
data_str = (char *)calloc(strlen((char*)data)+1, sizeof(char));
if (data_str == NULL)
{
printf("Error: failure in memory allocation.\n");
return -1;
}
strcpy(data_str, ((char *)(data)));
location = table->ratio * strHashFun(data_str, table->originalSize);
}
else
{
printf("Error: Invalid data type. \n");
return -1;
}
for (int i = location; i < location + table->ratio; i++) // Scan the array through the indexes given by the ratio variable and the hash variable.
{
current_object = table->arr[i];
if (current_object == NULL) // If there's an empty list, figure out what is the data-type and accordingly add the object to the array as the list's head.
{
if (table->dataType == INT_TYPE)
{
new_object = createObject(data_int);
table->arr[i] = new_object;
return i;
}
else
{
new_object = createObject(data_str);
table->arr[i] = new_object;
return i;
}
}
else if (listLength(current_object) < table->listLen) // If there is a list and it's not filled yet, go down the list and add the new object as the last element.
{
if (table->dataType == INT_TYPE)
{
new_object = createObject(data_int);
while (current_object->nextObj != NULL)
current_object = current_object->nextObj;
current_object->nextObj = new_object;
return i;
}
else
{
new_object = createObject(data_str);
while (current_object->nextObj != NULL)
current_object = current_object->nextObj;
current_object->nextObj = new_object;
return i;
}
}
} // If reached this area
duplicateTable(table);
if (table->dataType == INT_TYPE)
{
location = table->ratio * intHashFun(data_int, table->originalSize);
new_object = createObject(data_int);
table->arr[location + 1] = new_object;
return location + 1;
}
else
{
location = table->ratio * strHashFun(data_str, table->originalSize);
new_object = createObject(data_str);
table->arr[location + 1] = new_object;
return location + 1;
}
}
int isEqual(int type, void *data1, void *data2)
{
if (type == STR_TYPE)
{
return strcmp((char *)data1, (char *)data2);
}
else if (type == INT_TYPE)
{
if (*((int *)(data1)) == *((int *)(data2)))
return 0;
else
return 1;
}
else
{
printf("Error: Invalid data type. \n");
return -1;
}
}
Object *search(Table *table, void *data)
{
int location = -1;
Object *current_object;
if (table->dataType == INT_TYPE)
location = table->ratio * intHashFun(((int *)(data)), table->originalSize);
else
location = table->ratio * strHashFun((char *)(data), table->originalSize);
for (int i = location; i < location + table->ratio; i++)
{
current_object = table->arr[i];
if (listLength(table->arr[i]) > 0)
{
while (current_object != NULL)
{
if (table->dataType == INT_TYPE)
{
if (isEqual(table->dataType, (int *)(data), current_object->data) == 0)
return current_object;
}
else
{
if (isEqual(table->dataType, (char *)(data), current_object->data) == 0)
return current_object;
}
current_object = current_object->nextObj;
}
}
}
return NULL;
}
int removeObj(Table *table, void *data)
{
int location = -1;
Object *temp_object;
Object *temp_next;
if (table->dataType == INT_TYPE)
location = table->ratio * intHashFun(data, table->originalSize);
else
location = table->ratio * strHashFun(data, table->originalSize);
for (int i = location; i < location + table->ratio; i++)
{
temp_object = table->arr[i];
if (temp_object == NULL)
continue;
else if(table->dataType == INT_TYPE && isEqual(INT_TYPE,temp_object->data,data)==0 && temp_object->nextObj!=NULL)
{
table->arr[i]= temp_object->nextObj;
freeObject(temp_object,INT_TYPE);
return i;
}
else if(table->dataType == STR_TYPE && isEqual(STR_TYPE,temp_object->data,data)==0 && temp_object->nextObj!=NULL)
{
table->arr[i]= temp_object->nextObj;
freeObject(temp_object,STR_TYPE);
return i;
}
else if (temp_object->nextObj == NULL)
{
if (table->dataType == INT_TYPE)
{
if (isEqual(INT_TYPE, temp_object->data, data) == 0)
{
freeObject(table->arr[i], INT_TYPE);
table->arr[i] = NULL;
return i;
}
}
else
{
if (isEqual(STR_TYPE, temp_object->data, data) == 0)
{
freeObject(table->arr[i], STR_TYPE);
table->arr[i] = NULL;
return i;
}
}
}
else
{
while (temp_object->nextObj != NULL)
{
if (table->dataType == INT_TYPE)
{
if (isEqual(INT_TYPE, temp_object->nextObj->data, data) == 0)
{
temp_next=temp_object->nextObj->nextObj;
freeObject(temp_object->nextObj,INT_TYPE);
temp_object->nextObj = temp_next;
return i;
}
}
else
{
if (isEqual(STR_TYPE, temp_object->nextObj->data, data) == 0)
{
temp_next=temp_object->nextObj->nextObj;
freeObject(temp_object->nextObj,STR_TYPE);
temp_object->nextObj = temp_next;
return i;
}
}
temp_object = temp_object->nextObj;
}
}
}
return -1;
}
void freeObject(Object *obj, int type)
{
if(obj!=NULL)
{
free(obj->data);
free(obj);
}
}
void freeTable(Table* table)
{
Object* temp;
Object* current_object;
for(int i = 0; i < table->currentSize; i++)
{
if(table->arr[i] != NULL)
{
current_object = table->arr[i];
if(listLength(table->arr[i])==1)
{
freeObject(table->arr[i],table->dataType);
continue;
}
else if(listLength(table->arr[i]) > 1)
{
for(int j = 0; j < listLength(table->arr[i]);j++)
{
temp = current_object->nextObj;
freeObject(current_object,table->dataType);
current_object=temp;
}
//freeObject(table->arr[i],table->dataType);
}
}
}
free(table->arr);
free(table);
}
int main()
{
int a = 8;
int b = 16;
int c = 24;
int d = 5;
int e = 9;
int f = 13;
int g = 6;
int h = 10;
int i = 14;
int j = 104;
char *str1 = "aaaaaaaaaa";
char *str2 = "b r r r r e ";
char *str3 = "cwjxcn cwnjcwj";
char *str4 = "dwcnjwc njcwnjwc";
char *str5 = "ecwwc wcwc cwcw";
char *str6 = "f";
char *str7 = "ew33f";
Table *temp = createTable(8, 0, 2);
add(temp, (void *)&a);
add(temp, (void *)&b);
add(temp, (void *)&c);
add(temp, (void *)&d);
add(temp, (void *)&e);
add(temp, (void *)&f);
add(temp, (void *)&g);
add(temp, (void *)&h);
add(temp, (void *)&i);
printTable(temp);
Object *xyz = search(temp, (void *)&a);
if(xyz != NULL){
printf("a = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(temp, (void *)&c);
if(xyz != NULL){
printf("c = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(temp, (void *)&j);
if(xyz != NULL){
printf("j = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(temp, (void *)&f);
if(xyz != NULL){
printf("f = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
int x =removeObj(temp,(void*)&a);
int xx =removeObj(temp,(void*)&j);
int xxx =removeObj(temp,(void*)&a);
int y = removeObj(temp,(void*)&c);
int z = removeObj(temp,(void*)&i);
xyz = search(temp, (void *)&a);
printTable(temp);
if(xyz != NULL){
printf("a = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(temp, (void *)&f);
if(xyz != NULL){
printf("f = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(temp, (void *)&b);
if(xyz != NULL){
printf("b = %d\n", *(int*)xyz->data);
}
else{printf("NULL\n");}
printf("\n%d %d %d %d %d\n\n",x,xx,xxx,y,z);
Table *tempO = createTable(4, 1, 3);
add(tempO, (void *)str1);
add(tempO, (void *)str2);
add(tempO, (void *)str3);
add(tempO, (void *)str4);
add(tempO, (void *)str5);
add(tempO, (void *)str6);
printTable(tempO);
xyz = search(tempO, (void *)str1);
if(xyz != NULL){
printf("str1 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(tempO, (void *)str2);
if(xyz != NULL){
printf("str2 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(tempO, (void *)str3);
if(xyz != NULL){
printf("str3 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
add(tempO, (void *)str1);
add(tempO, (void *)str2);
add(tempO, (void *)str3);
add(tempO, (void *)str4);
add(tempO, (void *)str5);
add(tempO, (void *)str6);
printTable(tempO);
int x1 =removeObj(tempO,(void*)str6);
int xx1 =removeObj(tempO,(void*)str3);
int xxx1 =removeObj(tempO,(void*)str6);
int y1 = removeObj(tempO,(void*)str1);
int z1 = removeObj(tempO,(void*)str7);
printTable(tempO);
printf("\n%d %d %d %d %d\n\n",x1,xx1,xxx1,y1,z1);
xyz = search(tempO, (void *)str1);
if(xyz != NULL){
printf("str1 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(tempO, (void *)str2);
if(xyz != NULL){
printf("str2 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
xyz = search(tempO, (void *)str3);
if(xyz != NULL){
printf("str3 = %s\n", (char*)xyz->data);
}
else{printf("NULL\n");}
freeTable(temp);
freeTable(tempO);
return 0;
}
/*int main()
{
Table *t = createTable(4, STR_TYPE, 2);
char *c1 = "a";
char *c2 = "b";
char *c3 = "c";
char *c4 = "d";
add(t, (void *)c1);
add(t, (void *)c1);
add(t, (void *)c1);
add(t, (void *)c1);
//printTable(t);
add(t, (void *)c2);
add(t, (void *)c2);
add(t, (void *)c2);
add(t, (void *)c2);
//printTable(t);
add(t, (void *)c3);
add(t, (void *)c3);
add(t, (void *)c3);
add(t, (void *)c3);
//printTable(t);
add(t, (void *)c4);
add(t, (void *)c4);
add(t, (void *)c4);
add(t, (void *)c4);
printTable(t);
// printf("%s\n", ((char *)(search(t, c4)->data)));
removeObj(t,c4);
// printTable(t);
//removeObj(t,(char *)(search(t, c4)->data));
//removeObj(t,(char *)(search(t, c4)->data));
//removeObj(t,(char *)(search(t, c4)->data));
// removeObj(t,(char *)(search(t, c4)->data));
//printTable(t);
freeTable(t);
}
*/
Table* createTable(int size, int dType, int listLength);
/**
* The function release all the allocated members of struct Table.
*/
void freeTable(Table* table);
/**
* The function adds data to the hashtable (as described in the exe definition)
* On success, the function returns the array index of the added data, otherwise, it return -1.
*/
int add(Table* table, void* data);
/**
* The function removes the Object which its data equals to data, if there are more than one, it removes the first one.
* On success, the function returns the array index of the removed data, otherwise, it returns -1.
* -1 is also returned in the case where there is no such object.
*/
int removeObj(Table* table, void* data);
/**
* The function searches for an object that its data is equal to given data and returns a pointer to that object.
* If there is no such object or in a case of an error, NULL is returned.
*/
Object* search(Table* table, void* data);
/**
* The function prints the table (the format is in the exe definition)
*/
void printTable(Table* table);
/**
* This function creates an object and returns the pointer to it or NULL if there is some error.
*/
Object* createObject(void* data);
/**
* This function frees an object, note the if you allocated the data inside the element, it should also be freed.
* the type parameter is given for cases where not all types are dynamically allocated during Object creation.
*/
void freeObject(Object* obj, int type);
/**
* check the equality of the data of two objects. The implementation is different depending the type of the data.
* the function returns 0 if they are equal or some other value if they are not equal.
*/
int isEqual(int type, void* data1, void* data2);
/**
* returns the hash value of an integer, which is key mod origSize
*/
int intHashFun(int* key, int origSize);
/**
* returns the hash value of an string, which is m mod origSize, where m is the sum of the ascii value of all the
* character in key.
*/
int strHashFun(char* key, int origSize);
/**
* The function gets the table pointer and duplicated it's size, it also moves all the original data to their new location.
*/
void duplicateTable(Table *table);
/**
* The function gets the list pointer and counts elements in the list.
*/
int listLength(Object* obj);