diff --git a/avlTreeNew/AVLTree/AVLTree.sln b/avlTreeNew/AVLTree/AVLTree.sln new file mode 100644 index 0000000..1d6c315 --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree.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}") = "AVLTree", "AVLTree\AVLTree.vcxproj", "{4324245A-4186-4376-87B3-D0293B15F24B}" +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 + {4324245A-4186-4376-87B3-D0293B15F24B}.Debug|x64.ActiveCfg = Debug|x64 + {4324245A-4186-4376-87B3-D0293B15F24B}.Debug|x64.Build.0 = Debug|x64 + {4324245A-4186-4376-87B3-D0293B15F24B}.Debug|x86.ActiveCfg = Debug|Win32 + {4324245A-4186-4376-87B3-D0293B15F24B}.Debug|x86.Build.0 = Debug|Win32 + {4324245A-4186-4376-87B3-D0293B15F24B}.Release|x64.ActiveCfg = Release|x64 + {4324245A-4186-4376-87B3-D0293B15F24B}.Release|x64.Build.0 = Release|x64 + {4324245A-4186-4376-87B3-D0293B15F24B}.Release|x86.ActiveCfg = Release|Win32 + {4324245A-4186-4376-87B3-D0293B15F24B}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4226DC63-DC3D-43E1-9341-646B92A145E2} + EndGlobalSection +EndGlobal diff --git a/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj b/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj new file mode 100644 index 0000000..fca2ebb --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {4324245a-4186-4376-87b3-d0293b15f24b} + AVLTree + 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/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj.filters b/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj.filters new file mode 100644 index 0000000..3ef73b8 --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/AVLTree.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {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/avlTreeNew/AVLTree/AVLTree/avlTree.c b/avlTreeNew/AVLTree/AVLTree/avlTree.c new file mode 100644 index 0000000..a00a30c --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/avlTree.c @@ -0,0 +1,306 @@ +#include "avlTree.h" +#include +#include +#include +#include + +typedef struct Value { + char key[100]; + char* value; + int balance; +} Value; + +typedef struct Node { + Value data; + struct Node* left; + struct Node* right; +} Node; + +typedef struct Tree { + struct Node* root; +} Tree; + +int orderForBalance(Node* root, bool* isBalanced, int height) { + if (root != NULL) { + int leftHeight = orderForBalance(root->left, isBalanced, height); + int rightHeight = orderForBalance(root->right, isBalanced, height); + if (rightHeight - leftHeight != root->data.balance) { + *isBalanced = false; + } + return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1; + } + return 0; +} + +bool checkBalance(Tree* tree) { + bool isBalanced = true; + orderForBalance(tree->root, &isBalanced, 0); + return isBalanced; +} + +Tree* createTree(void) { + Tree* tree = calloc(1, sizeof(Tree)); + return tree; +} + +Node* createElementTree(void) { + Node* temp = calloc(1, sizeof(Node)); + return temp; +} + +void helpedClearTree(Node* root) { + if (root != NULL) { + helpedClearTree(root->left); + helpedClearTree(root->right); + free(root->data.value); + free(root); + } +} + +void clearTree(Tree* tree) { + if (tree == NULL) { + return; + } + helpedClearTree(tree->root); + free(tree); +} + +Node* rotateLeft(Node* a) { + Node* b = a->right; + Node* c = b->left; + if (b->data.balance == 0) { + b->data.balance += 1; + a->data.balance += -1; + } else { + b->data.balance = 0; + a->data.balance = 0; + } + b->left = a; + a->right = c; + return b; +} + +Node* rotateRight(Node* a) { + Node* b = a->left; + Node* c = b->right; + if (b->data.balance == 0) { + b->data.balance += -1; + a->data.balance += 1; + } else { + a->data.balance = 0; + b->data.balance = 0; + } + b->right = a; + a->left = c; + return b; +} + +Node* balance(Node* node) { + if (node->data.balance == 2) { + if (node->right->data.balance >= 0) { + return rotateLeft(node); + } + + node->right = rotateRight(node->right); + return rotateLeft(node); + } + if (node->data.balance == -2) { + if (node->left->data.balance <= 0) { + return rotateRight(node); + } + + node->left = rotateLeft(node->left); + return rotateRight(node); + } + return node; +} + +Node* helpedToInsert(Node* root, const char* key, char* string, const bool isKeyInTree, bool* needToChangeBalance) { + if (root == NULL) { + Node* newNode = createElementTree(); + newNode->data.value = string; + strcpy(newNode->data.key, key); + return newNode; + } + if (strcmp(root->data.key, key) == 0) { + free(root->data.value); + root->data.value = string; + return root; + } + if (strcmp(key, root->data.key) == -1) { + root->left = helpedToInsert(root->left, key, string, isKeyInTree, needToChangeBalance); + if (!isKeyInTree && !*needToChangeBalance) { + --root->data.balance; + } + } + else { + root->right = helpedToInsert(root->right, key, string, isKeyInTree, needToChangeBalance); + if (!isKeyInTree && !*needToChangeBalance) { + ++root->data.balance; + } + } + if (root->data.balance == 0) { + *needToChangeBalance = true; + } + Node* temp = balance(root); + if (temp->data.balance == 0) { + *needToChangeBalance = true; + } + return temp; +} + +void addToTree(Tree* tree, const char* key, char* string) { + bool needToChangeBalance = false; + tree->root = helpedToInsert(tree->root, key, string, isKeyInTree(tree, key), &needToChangeBalance); +} + +char* returnValueByKey(Tree* tree, const char* key) { + if (tree == NULL) { + return NULL; + } + Node* walker = tree->root; + + while (walker != NULL) { + if (strcmp(walker->data.key, key) == 0) { + return walker->data.value; + } + if (strcmp(walker->data.key, key) == -1) { + walker = walker->right; + } + else { + walker = walker->left; + } + } + return NULL; +} + +bool isKeyInTree(Tree* tree, const char* key) { + if (tree == NULL) { + return false; + } + Node* walker = tree->root; + + while (walker != NULL) { + if (strcmp(walker->data.key, key) == 0) { + return true; + } + if (strcmp(walker->data.key, key) == -1) { + walker = walker->right; + } + else { + walker = walker->left; + } + } + return false; +} + +Node* deleteNode(Node* root, const char* key, Tree* tree, Node* previousRoot, Node* theMostBigLeft, bool firstLeft, bool* needToChangeBalance, Node* previousMostBigLeft) { + if (!firstLeft && theMostBigLeft->right == NULL) { + Node* tempLeft = root->left; + free(root->data.value); + root->data.value = theMostBigLeft->data.value; + strcpy(root->data.key, theMostBigLeft->data.key); + if (theMostBigLeft->left != NULL && previousMostBigLeft != root) { + previousMostBigLeft->right = theMostBigLeft->left; + } + free(theMostBigLeft); + return NULL; + } else { + if (firstLeft) { + root->left = deleteNode(root, key, tree, previousRoot, root->left, false, needToChangeBalance, root); + if (!*needToChangeBalance) { + ++root->data.balance; + } + if (root->data.balance == -1 || root->data.balance == 1) { + *needToChangeBalance = true; + } + Node* temp = balance(root); + if (temp->data.balance == -1 || temp->data.balance == 1) { + *needToChangeBalance = true; + } + return temp; + } + else { + theMostBigLeft->right = deleteNode(root, key, tree, previousRoot, theMostBigLeft->right, false, needToChangeBalance, theMostBigLeft); + if (!*needToChangeBalance) { + --theMostBigLeft->data.balance; + } + if (theMostBigLeft->right == NULL) { + return theMostBigLeft; + } + } + } + if (root->data.balance == -1 || root->data.balance == 1) { + *needToChangeBalance = true; + } + Node* temp = balance(theMostBigLeft); + if (temp->data.balance == -1 || temp->data.balance == 1) { + *needToChangeBalance = true; + } + return temp; +} + +Node* helpDeleteNodeInTreeByKey(Node* root, const char* key, Tree* tree, Node* previousRoot, bool* needToChangeBalance) { + if (root == NULL) { + return NULL; + } + if (strcmp(root->data.key, key) == 0) { + if (root->left == NULL) { + Node* temp = root->right; + free(root->data.value); + free(root); + if (previousRoot == NULL) { + tree->root = temp; + } + else { + if (strcmp(previousRoot->data.key, key) == -1) { + previousRoot->right = temp; + } + else { + previousRoot->left = temp; + } + } + return temp; + } + root = deleteNode(root, key, tree, previousRoot, NULL, true, needToChangeBalance, root); + if (previousRoot == NULL) { + tree->root = root; + } + else { + if (strcmp(previousRoot->data.key, key) == -1) { + previousRoot->right = root; + } + else { + previousRoot->left = root; + } + } + return root; + } + if (strcmp(key, root->data.key) == -1) { + root->left = helpDeleteNodeInTreeByKey(root->left, key, tree, root, needToChangeBalance); + if (!*needToChangeBalance) { + ++root->data.balance; + } + } + else { + root->right = helpDeleteNodeInTreeByKey(root->right, key, tree, root, needToChangeBalance); + if (!*needToChangeBalance) { + --root->data.balance; + } + } + if (root->data.balance == -1 || root->data.balance == 1) { + *needToChangeBalance = true; + } + Node* temp = balance(root); + if (temp->data.balance == -1 || temp->data.balance == 1) { + *needToChangeBalance = true; + } + return temp; +} + +void deleteNodeInTreeByKey(Tree* tree, const char* key) { + if (isKeyInTree(tree, key)) { + bool needToChangeBalance = false; + tree->root = helpDeleteNodeInTreeByKey(tree->root, key, tree, NULL, &needToChangeBalance); + } +} \ No newline at end of file diff --git a/avlTreeNew/AVLTree/AVLTree/avlTree.h b/avlTreeNew/AVLTree/AVLTree/avlTree.h new file mode 100644 index 0000000..e1148d6 --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/avlTree.h @@ -0,0 +1,27 @@ +#ifndef AVL_TREE_H +#define AVL_TREE_H +#include + +typedef struct Tree Tree; + +// +Tree* createTree(void); + +// +void clearTree(Tree* tree); + +// +void addToTree(Tree* tree, const char* key, char* string); + +// +char* returnValueByKey(Tree* tree, const char* key); + +// +bool isKeyInTree(Tree* tree, const char* key); + +// +void deleteNodeInTreeByKey(Tree* tree, const char* key); + +// , +bool checkBalance(Tree* tree); +#endif \ No newline at end of file diff --git a/avlTreeNew/AVLTree/AVLTree/main.c b/avlTreeNew/AVLTree/AVLTree/main.c new file mode 100644 index 0000000..afd72ab --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/main.c @@ -0,0 +1,122 @@ +#include "avlTree.h" +#include "test.h" +#include +#include +#include +#include +#include + +int scanOne(); + +bool talkWithUser(void) { + printf(" :\n0 - \n1 - . , .\n2 - . , NULL.\n3 - .\n4- . , .\n"); + int command = scanOne(); + + while (command > 4 || command < 0) { + printf(" . !\n"); + command = scanOne(); + } + + Tree* tree = createTree(); + char* stringCopy = NULL; + + while (command != 0) { + printf(" . , 100 \n"); + char key[100] = { '\0' }; + int checkScanfKey = scanf("%s", key); + while (checkScanfKey != 1) { + while (getchar() != '\n') { + } + printf("...\n"); + checkScanfKey = scanf("%s", key); + } + + switch (command) { + case 1: + printf(" . 100 , \n"); + int size = scanOne(); + while (size < 0 || size > 100) { + while (getchar() != '\n') { + } + printf("...\n"); + size = scanOne(); + } + char buffer[101] = { '\0' }; + int checkScanf = scanf("%s", buffer); + + while (checkScanf != 1) { + while (getchar() != '\n') { + } + printf("...\n"); + checkScanf = scanf("%s", buffer); + } + size_t sizeBuffer = strlen(buffer); + char* string = calloc(sizeBuffer + 1, sizeof(char)); + if (string == NULL) { + return false; + } + for (size_t i = 0; i < sizeBuffer; ++i) { + string[i] = buffer[i]; + } + addToTree(tree, key, string); + break; + case 2: + stringCopy = returnValueByKey(tree, key); + if (string != NULL) { + printf("%s\n", string); + } + break; + case 3: + if (isKeyInTree(tree, key)) { + printf(", !\n"); + } + else { + printf(", !\n"); + } + break; + case 4: + deleteNodeInTreeByKey(tree, key); + break; + } + printf(" !\n"); + command = scanOne(); + + while (command > 4 || command < 0) { + printf(" . !\n"); + command = scanOne(); + } + } + + clearTree(tree); +} + +int main() { + setlocale(LC_ALL, "RUS"); + if (testForAvlTree()) { + printf(" !\n"); + } + else { + printf("...\n"); + return -1; + } + + if (!talkWithUser()) { + printf("...\n"); + return -1; + } +} + +int scanOne() { + int number = 0; + int checkScanf = scanf("%d", &number); + + while (checkScanf != 1) { + while (getchar() != '\n') { + } + + printf("...\n"); + checkScanf = scanf("%d", &number); + } + + return number; +} \ No newline at end of file diff --git a/avlTreeNew/AVLTree/AVLTree/test.c b/avlTreeNew/AVLTree/AVLTree/test.c new file mode 100644 index 0000000..2d50511 --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/test.c @@ -0,0 +1,61 @@ +#include "avlTree.h" +#include "test.h" +#include +#include +#include +#include + +bool testForAvlTree() { + Tree* tree = createTree(); + char* string1 = calloc(2, sizeof(char)); + if (string1 == NULL) { + return false; + } + string1[0] = 'a'; + char key1[] = "320"; + addToTree(tree, key1, string1); + char* string2 = calloc(2, sizeof(char)); + if (string2 == NULL) { + free(string1); + return false; + } + string2[0] = 'b'; + char key2[] = "200"; + addToTree(tree, key2, string2); + char* string3 = calloc(2, sizeof(char)); + if (string3 == NULL) { + clearTree(tree); + return false; + } + string3[0] = 'c'; + char key3[] = "100"; + addToTree(tree, key3, string3); + if (!isKeyInTree(tree, "100")) { + clearTree(tree); + return false; + } + for (int i = 0; i < 1000; ++i) { + char buffer[5] = { '\0' }; + _itoa(i, buffer, 10); + addToTree(tree, buffer, calloc(1, sizeof(char))); + } + if (!checkBalance(tree)) { + clearTree(tree); + return false; + } + deleteNodeInTreeByKey(tree, "100", true); + if (isKeyInTree(tree, "100")) { + clearTree(tree); + return false; + } + deleteNodeInTreeByKey(tree, "200", true); + char stringForCheck[2] = { '\0' }; + stringForCheck[0] = 'a'; + if (strcmp(returnValueByKey(tree, "320"), stringForCheck) != 0) { + clearTree(tree); + return false; + } + deleteNodeInTreeByKey(tree, "320", true); + clearTree(tree); + return true; +} \ No newline at end of file diff --git a/avlTreeNew/AVLTree/AVLTree/test.h b/avlTreeNew/AVLTree/AVLTree/test.h new file mode 100644 index 0000000..6a9d474 --- /dev/null +++ b/avlTreeNew/AVLTree/AVLTree/test.h @@ -0,0 +1,8 @@ +#ifndef TEST_H +#define TEST_H +#include + +//Tests for tree +bool testForAvlTree(); + +#endif \ No newline at end of file