CCCPaste

AISD_Tree

#include 
#include 
#include 

typedef struct Node {
    int data;
    struct Node* left;
    struct Node* right;
    int isThreaded;
} Node;


Node* createNode(int data);
Node* insert(Node* root, int data);
void printTree(Node* root, int level, int showThreads);
void inorder(Node* root);
void preorder(Node* root);
void postorder(Node* root);
void createThreadedBST(Node* root, Node** lastNode);
void threadedInorderTraversal(Node* root);
Node* leftMost(Node* node);
void deleteSubtree(Node** root, int key);
void freeTree(Node* root);
void clearInputBuffer();
int search(Node* root, int key);
void deleteSubtreeRecursive(Node** root, int key);
Node* copyTree(Node* root);

int main() {
    Node* root = NULL;
    Node* threadedRoot = NULL;
    int choice, data, key;
    Node* lastNode = NULL;

    while (1) {
        printf("1. Построить дерево двоичного поиска и вывести\n");
        printf("2. Выполнить 3 полных обхода (с выделением)\n");
        printf("3. Сделать симметричную правую прошивку и вывести\n");
        printf("4. Удаление из прошитого дерева и вывод\n");
        printf("5. Выход\n");
        printf("Выберите пункт: ");

        if (scanf("%d", &choice) != 1) {
            printf("Ошибка ввода!\n");
            clearInputBuffer();
            continue;
        }
        clearInputBuffer();

        switch (choice) {
            case 1:
                freeTree(root);
                freeTree(threadedRoot);
                root = NULL;
                threadedRoot = NULL;

                printf("Введите элементы (для завершения введите -1):\n");
                while (1) {
                    printf("Элемент: ");
                    if (scanf("%d", &data) != 1) {
                        printf("Некорректный ввод. Попробуйте снова.\n");
                        clearInputBuffer();
                        continue;
                    }
                    if (data == -1) break;
                    root = insert(root, data);
                }
                printf("\nДерево:\n");
                printTree(root, 0, 0);
                break;

            case 2:
                if (root == NULL) {
                    printf("Дерево пусто!\n");
                    break;
                }
                printf("\nПрямой обход (трассировка): ");
                preorder(root);
                printf("\nСимметричный обход (трассировка): ");
                inorder(root);
                printf("\nОбратный обход (трассировка): ");
                postorder(root);
                printf("\n");
                break;

            case 3:
                if (root == NULL) {
                    printf("Дерево пусто!\n");
                    break;
                }
                freeTree(threadedRoot);
                threadedRoot = copyTree(root);
                lastNode = NULL;
                createThreadedBST(threadedRoot, &lastNode);

                if (lastNode != NULL && lastNode->right == NULL) {
                    lastNode->right = threadedRoot;
                    lastNode->isThreaded = 1;
                }

                printf("\nПрошитый симметричный обход: ");
                threadedInorderTraversal(threadedRoot);
                printf("\n\nПрошитое дерево:\n");
                printTree(threadedRoot, 0, 1);
                break;

            case 4:
                if (root == NULL) {
                    printf("Дерево пусто!\n");
                    break;
                }
                printf("Введите ключ для удаления: ");
                if (scanf("%d", &key) != 1) {
                    printf("Ошибка ввода!\n");
                    clearInputBuffer();
                    break;
                }
                if (!search(root, key)) {
                    printf("Элемент %d не найден.\n", key);
                }
                else {
                    deleteSubtree(&root, key);
                    deleteSubtree(&threadedRoot, key);

                    if (threadedRoot != NULL) {
                        lastNode = NULL;
                        createThreadedBST(threadedRoot, &lastNode);

                        if (lastNode != NULL && lastNode->right == NULL) {
                            lastNode->right = threadedRoot;
                            lastNode->isThreaded = 1;
                        }
                    }

                    printf("\nПосле удаления:\n");
                    printf("Исходное дерево:\n");
                    printTree(root, 0, 0);
                    printf("\nПрошитое дерево:\n");
                    printTree(threadedRoot, 0, 1);
                    printf("\nОбновлённый прошитый обход: ");
                    threadedInorderTraversal(threadedRoot);
                    printf("\n");
                }
                break;

            case 5:
                freeTree(root);
                freeTree(threadedRoot);
                printf("Программа завершена.\n");
                return 0;

            default:
                printf("Неверный выбор! Попробуйте снова.\n");
        }
    }
    return 0;
}

Node* createNode(int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("Ошибка выделения памяти!\n");
        exit(1);
    }
    newNode->data = data;
    newNode->left = NULL;
    newNode->right = NULL;
    newNode->isThreaded = 0;
    return newNode;
}

Node* insert(Node* root, int data) {
    if (root == NULL) return createNode(data);
    if (data < root->data)
        root->left = insert(root->left, data);
    else if (data > root->data)
        root->right = insert(root->right, data);
    return root;
}

int search(Node* root, int key) {
    if (root == NULL) return 0;
    if (key == root->data) return 1;
    if (key < root->data) return search(root->left, key);
    if (!root->isThreaded) return search(root->right, key);
    return 0;
}

void printTree(Node* root, int level, int showThreads) {
    if (root == NULL) return;

    for (int i = 0; i < level; i++) {
        printf("    ");
    }
    printf("%d", root->data);

    if (showThreads && root->isThreaded && root->right != NULL) {
        printf(" (%d)", root->right->data);
    }
    printf("\n");

    int hasLeft = (root->left != NULL);
    int hasRight = (!root->isThreaded && root->right != NULL);

    if (hasLeft && hasRight) {
        printTree(root->left, level + 1, showThreads);
        printTree(root->right, level + 1, showThreads);
    }

    else if (hasLeft && !hasRight) {
        printTree(root->left, level + 1, showThreads);
        for (int i = 0; i < level + 1; i++) {
            printf("    ");
        }
        printf("-\n");
    }

    else if (!hasLeft && hasRight) {
        for (int i = 0; i < level + 1; i++) {
            printf("    ");
        }
        printf("-\n");
        printTree(root->right, level + 1, showThreads);
    }

}


void inorder(Node* root) {
    if (root == NULL) {
        printf("0 ");
        return;
    }
    printf("%d ", root->data);
    inorder(root->left);
    printf("(%d) ", root->data);
    inorder(root->right);
    printf("%d ", root->data);
}


void preorder(Node* root) {
    if (root == NULL) {
        printf("0 ");
        return;
    }
    printf("(%d) ", root->data);
    preorder(root->left);
    printf("%d ", root->data);
    preorder(root->right);
    printf("%d ", root->data);
}

void postorder(Node* root) {
    if (root == NULL) {
        printf("0 ");
        return;
    }
    printf("%d ", root->data);
    postorder(root->left);
    printf("%d ", root->data);
    postorder(root->right);
    printf("(%d) ", root->data);
}

Node* leftMost(Node* node) {
    if (node == NULL) return NULL;
    while (node->left != NULL)
        node = node->left;
    return node;
}


void createThreadedBST(Node* root, Node** lastNode) {
    if (root == NULL) return;

    createThreadedBST(root->left, lastNode);

    if (*lastNode != NULL && (*lastNode)->right == NULL) {
        (*lastNode)->right = root;
        (*lastNode)->isThreaded = 1;
    }
    *lastNode = root;

    if (!root->isThreaded) {
        createThreadedBST(root->right, lastNode);
    }
}

void threadedInorderTraversal(Node* root) {
    if (root == NULL) {
        printf("(пусто)");
        return;
    }

    Node* current = leftMost(root);
    int first = 1;
    int rootVisited = 0;

    while (current != NULL) {
        if (!first) {
            printf(" ");
        }
        printf("%d", current->data);
        first = 0;

        if (current == root) {
            if (rootVisited) {
                break;
            }
            rootVisited = 1;
        }

        if (current->isThreaded) {
            current = current->right;
        }
        else {
            current = leftMost(current->right);
        }
    }
}

Node* copyTree(Node* root) {
    if (root == NULL) return NULL;

    Node* newNode = createNode(root->data);
    newNode->left = copyTree(root->left);
    newNode->right = copyTree(root->right);
    newNode->isThreaded = 0;

    return newNode;
}


void deleteSubtree(Node** root, int key) {
    if (*root == NULL) return;


    if ((*root)->data == key) {
        freeTree(*root);
        *root = NULL;
        return;
    }

    deleteSubtreeRecursive(root, key);
}

void deleteSubtreeRecursive(Node** root, int key) {
    if (*root == NULL) return;

    if ((*root)->data == key) {
        Node* leftSubtree = (*root)->left;
        Node* rightSubtree = (*root)->right;

        free(*root);

        if (leftSubtree != NULL && rightSubtree != NULL) {
            Node* maxNode = leftSubtree;
            while (maxNode->right != NULL && !maxNode->isThreaded) {
                maxNode = maxNode->right;
            }
            *root = maxNode;
            maxNode->left = (maxNode != leftSubtree) ? leftSubtree : maxNode->left;
            maxNode->right = rightSubtree;
        }
        else if (leftSubtree != NULL) {
            *root = leftSubtree;
        }
        else {
            *root = rightSubtree;
        }
        return;
    }

    if (key < (*root)->data) {
        deleteSubtreeRecursive(&(*root)->left, key);
    } else {
        deleteSubtreeRecursive(&(*root)->right, key);
    }
}

void freeTree(Node* root) {
    if (root == NULL) return;
    freeTree(root->left);
    if (!root->isThreaded) {
        freeTree(root->right);
    }
    free(root);
}

void clearInputBuffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}