Загрузка данных


#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

struct ttree {
    int inf;
    ttree *left;
    ttree *right;
};

// Функция создания сбалансированного дерева поиска
ttree* createBalancedTree(int arr[], int start, int end) {
    if (start > end) return NULL;
    int mid = (start + end) / 2;
    ttree *root = new ttree;
    root->inf = arr[mid];
    root->left = createBalancedTree(arr, start, mid - 1);
    root->right = createBalancedTree(arr, mid + 1, end);
    return root;
}

// Добавление нового элемента
ttree* addtree(ttree *proot, int inf) {
    ttree *nl = new ttree;
    nl->inf = inf;
    nl->left = NULL;
    nl->right = NULL;
    if (proot == NULL) return nl;
    
    ttree *ps = proot, *pr;
    bool b;
    while (ps != NULL) {
        pr = ps;
        b = (inf < ps->inf);
        if (b) ps = ps->left;
        else ps = ps->right;
    }
    if (b) pr->left = nl;
    else pr->right = nl;
    return proot;
}

// Прямой обход (Корень-Лево-Право)
void preorder(ttree *p) {
    if (p == NULL) return;
    cout << p->inf << " ";
    preorder(p->left);
    preorder(p->right);
}

// Обратный обход (Лево-Право-Корень)
void postorder(ttree *p) {
    if (p == NULL) return;
    postorder(p->left);
    postorder(p->right);
    cout << p->inf << " ";
}

// Симметричный обход (возрастание)
void inorder(ttree *p) {
    if (p == NULL) return;
    inorder(p->left);
    cout << p->inf << " ";
    inorder(p->right);
}

// Поиск элемента с заданным ключом
bool search(ttree *p, int key) {
    if (p == NULL) return false;
    if (p->inf == key) return true;
    if (key < p->inf) return search(p->left, key);
    else return search(p->right, key);
}

// Удаление всего дерева
ttree* deltree(ttree *p) {
    if (p == NULL) return NULL;
    deltree(p->left);
    deltree(p->right);
    delete p;
    return NULL;
}

// Удаление элемента с заданным ключом
ttree* dellist(ttree *proot, int inf) {
    ttree *ps = proot, *pr = proot, *w, *v;
    
    while ((ps != NULL) && (ps->inf != inf)) {
        pr = ps;
        if (inf < ps->inf) ps = ps->left;
        else ps = ps->right;
    }
    
    if (ps == NULL) return proot;
    
    if ((ps->left == NULL) && (ps->right == NULL)) {
        if (ps == pr) {
            delete ps;
            return NULL;
        }
        if (pr->left == ps) pr->left = NULL;
        else pr->right = NULL;
        delete ps;
        return proot;
    }
    
    if (ps->left == NULL) {
        if (ps == pr) {
            ps = ps->right;
            delete pr;
            return ps;
        }
        if (pr->left == ps) pr->left = ps->right;
        else pr->right = ps->right;
        delete ps;
        return proot;
    }
    
    if (ps->right == NULL) {
        if (ps == pr) {
            ps = ps->left;
            delete pr;
            return ps;
        }
        if (pr->left == ps) pr->left = ps->left;
        else pr->right = ps->left;
        delete ps;
        return proot;
    }
    
    w = ps->left;
    if (w->right == NULL) {
        w->right = ps->right;
    } else {
        while (w->right != NULL) {
            v = w;
            w = w->right;
        }
        v->right = w->left;
        w->left = ps->left;
        w->right = ps->right;
    }
    if (ps == pr) {
        delete ps;
        return w;
    }
    if (pr->left == ps) pr->left = w;
    else pr->right = w;
    delete ps;
    return proot;
}

// Задание 3: Удаление ветви с вершиной, имеющей заданный ключ
ttree* deleteBranch(ttree *root, int key) {
    if (root == NULL) return NULL;
    if (root->inf == key) {
        deltree(root);
        return NULL;
    }
    if (key < root->inf) {
        if (root->left != NULL && root->left->inf == key) {
            root->left = deltree(root->left);
        } else {
            root->left = deleteBranch(root->left, key);
        }
    } else {
        if (root->right != NULL && root->right->inf == key) {
            root->right = deltree(root->right);
        } else {
            root->right = deleteBranch(root->right, key);
        }
    }
    return root;
}

// Задание 9: Определить число узлов, у которых есть указатель только на одну ветвь
int countSingleChildNodes(ttree *root) {
    if (root == NULL) return 0;
    int count = 0;
    if ((root->left == NULL && root->right != NULL) || 
        (root->left != NULL && root->right == NULL)) {
        count = 1;
    }
    return count + countSingleChildNodes(root->left) + countSingleChildNodes(root->right);
}

// Вспомогательная функция для задания 12: сбор всех значений
void collectValues(ttree *root, vector<int>& values) {
    if (root == NULL) return;
    collectValues(root->left, values);
    values.push_back(root->inf);
    collectValues(root->right, values);
}

// Задание 12: Найти среднее значение всех ключей и узел с ближайшим ключом
void findClosestToAverage(ttree *root, double avg, int &closestKey, double &minDiff) {
    if (root == NULL) return;
    double diff = abs(root->inf - avg);
    if (diff < minDiff) {
        minDiff = diff;
        closestKey = root->inf;
    }
    findClosestToAverage(root->left, avg, closestKey, minDiff);
    findClosestToAverage(root->right, avg, closestKey, minDiff);
}

pair<double, int> task12(ttree *root) {
    vector<int> values;
    collectValues(root, values);
    
    double sum = 0;
    for (int v : values) sum += v;
    double avg = sum / values.size();
    
    int closestKey = values[0];
    double minDiff = abs(values[0] - avg);
    findClosestToAverage(root, avg, closestKey, minDiff);
    
    return {avg, closestKey};
}

// Задание 14: Определить количество узлов в левой ветви дерева
int countLeftBranch(ttree *root) {
    if (root == NULL || root->left == NULL) return 0;
    return 1 + countLeftBranch(root->left) + countNodes(root->left->right);
}

// Вспомогательная функция для подсчета всех узлов поддерева
int countNodes(ttree *root) {
    if (root == NULL) return 0;
    return 1 + countNodes(root->left) + countNodes(root->right);
}

int main() {
    srand(time(0));
    
    // 1. Создание сбалансированного дерева из чисел [-50, 50] с шагом 10
    int arr[] = {-50, -40, -30, -20, -10, 0, 10, 20, 30, 40, 50};
    int n = sizeof(arr) / sizeof(arr[0]);
    ttree *root = createBalancedTree(arr, 0, n - 1);
    
    cout << "Сбалансированное дерево создано из чисел: ";
    for (int i = 0; i < n; i++) cout << arr[i] << " ";
    cout << endl;
    
    // Вывод обходов
    cout << "\nПрямой обход: ";
    preorder(root);
    cout << "\nОбратный обход: ";
    postorder(root);
    cout << "\nСимметричный обход (возрастание): ";
    inorder(root);
    cout << endl;
    
    // Демонстрация основных операций
    cout << "\n=== Демонстрация операций ===" << endl;
    
    // Добавление
    root = addtree(root, 25);
    root = addtree(root, -35);
    cout << "После добавления 25 и -35: ";
    inorder(root);
    cout << endl;
    
    // Поиск
    cout << "Поиск 25: " << (search(root, 25) ? "найден" : "не найден") << endl;
    
    // Удаление
    root = dellist(root, 25);
    cout << "После удаления 25: ";
    inorder(root);
    cout << endl;
    
    // Задание 3: Удаление ветви с вершиной -30
    cout << "\n=== Задание 3: Удаление ветви с ключом -30 ===" << endl;
    root = deleteBranch(root, -30);
    cout << "Дерево после удаления ветви: ";
    inorder(root);
    cout << endl;
    
    // Задание 9: Узлы с одной дочерью
    cout << "\n=== Задание 9: Узлы с одной дочерью ===" << endl;
    cout << "Количество узлов с одной дочерью: " << countSingleChildNodes(root) << endl;
    
    // Задание 12: Среднее и ближайший узел
    cout << "\n=== Задание 12: Ближайший к среднему ===" << endl;
    auto [avg, closest] = task12(root);
    cout << "Среднее значение: " << avg << endl;
    cout << "Ближайший ключ: " << closest << endl;
    
    // Задание 14: Узлы в левой ветви
    cout << "\n=== Задание 14: Левая ветвь ===" << endl;
    cout << "Узлов в левой ветви: " << countLeftBranch(root) << endl;
    
    // Освобождение памяти
    root = deltree(root);
    
    return 0;
}