diff --git a/hashTable/hashTable.sln b/hashTable/hashTable.sln new file mode 100644 index 0000000..acb8f9e --- /dev/null +++ b/hashTable/hashTable.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hashTable", "hashTable\hashTable.vcxproj", "{95F90EAD-136D-4C34-A865-9E53811D167C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {95F90EAD-136D-4C34-A865-9E53811D167C}.Debug|x64.ActiveCfg = Debug|x64 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Debug|x64.Build.0 = Debug|x64 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Debug|x86.ActiveCfg = Debug|Win32 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Debug|x86.Build.0 = Debug|Win32 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Release|x64.ActiveCfg = Release|x64 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Release|x64.Build.0 = Release|x64 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Release|x86.ActiveCfg = Release|Win32 + {95F90EAD-136D-4C34-A865-9E53811D167C}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C8C7A619-4AC6-4277-9DF1-6A284BD7E9D0} + EndGlobalSection +EndGlobal diff --git a/hashTable/hashTable/hash.c b/hashTable/hashTable/hash.c new file mode 100644 index 0000000..b121148 --- /dev/null +++ b/hashTable/hashTable/hash.c @@ -0,0 +1,132 @@ +#include "hash.h" +#include "list.h" +#include +#include +#include +#include + +typedef struct ElementsHashTable { + struct List* list; +} ElementsHashTable; + +struct HashTable { + struct ElementsHashTable** arrayHash; + int hashSize; +}; + +HashTable* createHashArray(int* errorCode, int size) { + HashTable* table = calloc(1, sizeof(HashTable)); + if (table == NULL) { + *errorCode = -1; + return NULL; + } + table->hashSize = size; + table->arrayHash = (ElementsHashTable**)malloc(size * sizeof(ElementsHashTable*)); + if (table->arrayHash == NULL) { + *errorCode = -1; + return; + } + for (int i = 0; i < size; ++i) { + table->arrayHash[i] = (ElementsHashTable*)malloc(1 * sizeof(ElementsHashTable)); + if (table->arrayHash[i] == NULL) { + for (int j = 0; j < i; ++j) { + free(table->arrayHash[j]); + } + *errorCode = -1; + return NULL; + } + table->arrayHash[i]->list = NULL; + } + return table; +} + +int fastPow(int number, int degree) { + if (degree < 0) { + return 1.0 / fastPow(number, abs(degree)); + } + if (degree == 0) { + return 1; + } + if (degree % 2 == 0) { + const int copyElement = fastPow(number, degree / 2); + return copyElement * copyElement; + } + return fastPow(number, degree - 1) * number; +} + +int hashFunction(char string[], int size) { + int result = 0; + int simpleNumber = 7; + int neededNumber = fastPow(simpleNumber, (int)strlen(string) - 1); + for (int i = 0; string[i] != '\0'; ++i) { + result += string[i] * neededNumber; + neededNumber /= simpleNumber; + } + return abs(result) % size; +} + +void addToHashTable(HashTable* table, char string[], int* errorCode) { + int index = hashFunction(string, table->hashSize); + if (table->arrayHash[index]->list == NULL) { + table->arrayHash[index]->list = createList(errorCode); + if (*errorCode == -1) { + return; + } + } + insertToList(table->arrayHash[index]->list, string, errorCode); +} + +void printHashTable(HashTable* table) { + if (table == NULL || table->arrayHash == NULL) { + return; + } + for (int i = 0; i < table->hashSize; ++i) { + if (table->arrayHash[i]->list != NULL) { + printf("%d)", i); + printList(table->arrayHash[i]->list); + } else { + printf("%d)\n", i); + } + } +} + +void clearHashTable(HashTable* table) { + for (int i = 0; i < table->hashSize; ++i) { + if (table->arrayHash[i]->list != NULL) { + clearList(table->arrayHash[i]->list); + } + } + free(table->arrayHash); + free(table); + table = NULL; +} + +double fillFactor(HashTable* table) { + double busy = 0; + for (int i = 0; i < table->hashSize; ++i) { + if (table->arrayHash[i]->list != NULL) { + ++busy; + } + } + return busy == 0 ? -1 : busy / (double)table->hashSize; +} + +bool ifAllInTableWithoutIdentical(HashTable* table, char** buffer, int sizeBuffer) { + if (table == NULL) { + if (buffer == NULL) { + return true; + } + return false; + } + int howMuchInTable = 0; + for (int i = 0; i < table->hashSize; ++i) { + if (table->arrayHash[i]->list != NULL) { + for (int j = 0; j < sizeBuffer; ++j) { + if (findStringInList(table->arrayHash[i]->list, buffer[j])) { + ++howMuchInTable; + } + } + } + } + return howMuchInTable == sizeBuffer; +} \ No newline at end of file diff --git a/hashTable/hashTable/hash.h b/hashTable/hashTable/hash.h new file mode 100644 index 0000000..22788cb --- /dev/null +++ b/hashTable/hashTable/hash.h @@ -0,0 +1,22 @@ +#pragma once +#include + +typedef struct HashTable HashTable; + +//Create hash-table +HashTable* createHashArray(int* errorCode, int size); + +//Add to hash-table +void addToHashTable(HashTable* table, char string[], int* errorCode); + +//Print hash-table +void printHashTable(HashTable* table); + +//Clear hash-table +void clearHashTable(HashTable* table); + +//find fill factor hash-table +double fillFactor(HashTable* table); + +//Only for test +bool ifAllInTableWithoutIdentical(HashTable* table, char** buffer, int sizeBuffer); \ No newline at end of file diff --git a/hashTable/hashTable/hashTable.vcxproj b/hashTable/hashTable/hashTable.vcxproj new file mode 100644 index 0000000..bf26bd1 --- /dev/null +++ b/hashTable/hashTable/hashTable.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {95f90ead-136d-4c34-a865-9e53811d167c} + hashTable + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + false + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hashTable/hashTable/hashTable.vcxproj.filters b/hashTable/hashTable/hashTable.vcxproj.filters new file mode 100644 index 0000000..7912354 --- /dev/null +++ b/hashTable/hashTable/hashTable.vcxproj.filters @@ -0,0 +1,47 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + + + Исходные файлы + + + Исходные файлы + + + Исходные файлы + + + + + Исходные файлы + + + \ No newline at end of file diff --git a/hashTable/hashTable/list.c b/hashTable/hashTable/list.c new file mode 100644 index 0000000..20c2c03 --- /dev/null +++ b/hashTable/hashTable/list.c @@ -0,0 +1,125 @@ +#include "list.h" +#include +#include +#include +#include + +typedef struct Node { + char value[100]; + int size; + struct Node* next; +} Node; + +typedef struct List { + struct Node* head; +}; + +Node* newNode(int* errorCode, char value[]) { + Node* temp = calloc(1, sizeof(Node)); + if (temp == NULL) { + *errorCode = -1; + return NULL; + } + strcpy(temp->value, value); + ++temp->size; + return temp; +} + +void insertToList(List* list, char value[], int *errorCode) { + if (list == NULL) { + *errorCode = -1; + return; + } + if (list->head == NULL) { + list->head = newNode(errorCode, value); + return; + } + Node* walker = list->head; + while (walker->next != NULL) { + if (strcmp(walker->value, value) == 0) { + ++walker->size; + return; + } + walker = walker->next; + } + if (strcmp(walker->value, value) == 0) { + ++walker->size; + return; + } + walker->next = newNode(errorCode, value); +} + +void helpedClearList(Node* element) { + if (element) { + helpedClearList(element->next); + free(element); + } +} + +void clearList(List* list) { + if (list == NULL) { + return; + } + helpedClearList(list->head); + free(list); + list = NULL; + return; +} + +void deleteNode(List* list, char value[]) { + if (list == NULL || list->head == NULL) { + return; + } + if (strcmp(value, list->head->value) == 0) { + Node* temp = list->head->next; + free(list->head); + list->head = temp; + return; + } + Node* walker = list->head; + while (walker->next != NULL && strcmp(walker->next->value, value) != 0) { + walker = walker->next; + } + if (walker->next != NULL) { + free(walker->next); + walker->next = NULL; + } +} + +List* createList(int *errorCode) { + List* list = calloc(1, sizeof(List)); + if (list == NULL) { + *errorCode = -1; + return NULL; + } + list->head = NULL; + return list; +} + +void printList(List* list) { + if (list == NULL || list->head == NULL) { + return; + } + Node* walker = list->head; + int i = 0; + while (walker != NULL) { + printf("\n%d: %s -- %d", i, walker->value, walker->size); + walker = walker->next; + ++i; + } + printf("\n"); +} + +bool findStringInList(List* list, char value[]) { + if (list == NULL) { + return false; + } + Node* walker = list->head; + while (walker != NULL) { + if (strcmp(walker->value, value) == 0) { + return true; + } + walker = walker->next; + } + return false; +} \ No newline at end of file diff --git a/hashTable/hashTable/list.h b/hashTable/hashTable/list.h new file mode 100644 index 0000000..151fb5e --- /dev/null +++ b/hashTable/hashTable/list.h @@ -0,0 +1,22 @@ +#pragma once +#include + +typedef struct List List; + +//Add elements to list +void insertToList(List* list, char value[], int* errorCode); + +//Clear list +void clearList(List* list); + +//Delete node in list +void deleteNode(List* list, char value[]); + +//create new list +List* createList(int* errorCode); + +//Print list +void printList(List* list); + +//Is string in List +bool findStringInList(List* list, char value[]); \ No newline at end of file diff --git a/hashTable/hashTable/main.c b/hashTable/hashTable/main.c new file mode 100644 index 0000000..55c6c9d --- /dev/null +++ b/hashTable/hashTable/main.c @@ -0,0 +1,55 @@ +#include "list.h" +#include "hash.h" +#include "test.h" +#include +#include + +int main() { + if (test()) { + printf("Test correct\n"); + } else { + printf("Problems...\n"); + return -1; + } + printf("Enter a more appropriate hash table size\n"); + int size = 0; + int checkScanf = scanf("%d", &size); + while (checkScanf != 1) { + while (getchar() != '\n') { + } + printf("ERROR\n"); + checkScanf = scanf("%d", &size); + } + printf("Print file name with its extension <100 symbols\n"); + char fileName[100] = { '\0' }; + checkScanf = scanf("%s", &fileName); + while (checkScanf != 1) { + while (getchar() != '\n') { + } + printf("ERROR\n"); + checkScanf = scanf("%s", &fileName); + } + int errorCode = 0; + HashTable* table = createHashArray(&errorCode, size); + if (errorCode == -1) { + printf("Memmory error\n"); + return -1; + } + FILE* file = fopen(fileName, "r"); + if (file == NULL) { + printf("Mistake!"); + return -1; + } + char data[100] = { '\0' }; + while (fscanf(file, "%s", data) == 1) { + addToHashTable(table, data, &errorCode); + if (errorCode == -1) { + printf("Memmory error\n"); + return -1; + } + } + fclose(file); + printHashTable(table); + printf("%f", fillFactor(table)); + clearHashTable(table); +} \ No newline at end of file diff --git a/hashTable/hashTable/test.c b/hashTable/hashTable/test.c new file mode 100644 index 0000000..5d75fe7 --- /dev/null +++ b/hashTable/hashTable/test.c @@ -0,0 +1,37 @@ +#include "hash.h" +#include +#include +#include + +bool test(void) { + int errorCode = 0; + HashTable* table = createHashArray(&errorCode, 4); + if (errorCode == -1) { + return false; + } + if (table == NULL) { + return false; + } + char bufferFirst[4] = { 'a', 'b', 'c', '\0'}; + char bufferSecond[4] = { 'a', 'c', 'b', '\0'}; + addToHashTable(table, bufferFirst, &errorCode); + if (errorCode == -1) { + return false; + } + addToHashTable(table, bufferSecond, &errorCode); + if (errorCode == -1) { + return false; + } + char** buffer = (char**)malloc(2 * sizeof(char*)); + if (buffer == NULL) { + return false; + } + buffer[0] = bufferFirst; + buffer[1] = bufferSecond; + bool testResult = ifAllInTableWithoutIdentical(table, buffer, 2); + clearHashTable(table); + free(buffer); + return testResult; +} +//Resize - 2 +//FillFacot - 1 \ No newline at end of file diff --git a/hashTable/hashTable/test.h b/hashTable/hashTable/test.h new file mode 100644 index 0000000..de74744 --- /dev/null +++ b/hashTable/hashTable/test.h @@ -0,0 +1,5 @@ +#pragma once +#include + +//Test for hash-table +bool test(void); \ No newline at end of file diff --git a/hashTable/hashTable/text.txt b/hashTable/hashTable/text.txt new file mode 100644 index 0000000..5e7ad8b --- /dev/null +++ b/hashTable/hashTable/text.txt @@ -0,0 +1 @@ +Calculate the frequency of occurrence of words in the text using a hash table. At the input of the text file, output to the console all the words that occur in this text with the number of times that each word occurs. A word is a sequence of characters separated by spaces, different word forms are considered different words. Implement the hash table in a separate module using the "List" module. Calculate and output also the hash table fill factor, the maximum and average length of the list in the table segment. The number of "free" attempts to surrender \ No newline at end of file