Загрузка данных
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <vector>
using namespace std;
// Структура узла бинарного дерева поиска
struct ttree {
int inf; // ключ (информация)
ttree *left; // указатель на левое поддерево
ttree *right; // указатель на правое подерево
};
// Функция создания нового узла
ttree* createNode(int inf) {
ttree *nl = new ttree;
nl->inf = inf;
nl->left = NULL;
nl->right = NULL;
return nl;
}
// Добавление элемента в бинарное дерево поиска (без балансировки)
ttree* addtree(ttree *proot, int inf) {
ttree *nl = createNode(inf);
if (proot == NULL) return nl;
ttree *ps = proot;
ttree *pr = NULL;
bool b = false; // направление: true - влево, false - вправо
while (ps != NULL) {
pr = ps;
if (inf < ps->inf) {
b = true;
ps = ps->left;
} else {
b = false;
ps = ps->right;
}
}
if (b)
pr->left = nl;
else
pr->right = nl;
return proot;
}
// Симметричный обход (в порядке возрастания ключей)
void inorder(ttree *p) {
if (p == NULL) return;
inorder(p->left);
cout << p->inf << " ";
inorder(p->right);
}
// Прямой обход (корень -> левое -> правое)
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 << " ";
}
// Поиск элемента с заданным ключом (возвращает true и значение, если найден)
bool search(ttree *p, int key, int &found) {
if (p == NULL) return false;
if (p->inf == key) {
found = p->inf;
return true;
}
if (key < p->inf)
return search(p->left, key, found);
else
return search(p->right, key, found);
}
// Удаление всего дерева (освобождение памяти)
ttree* deltree(ttree *p) {
if (p == NULL) return NULL;
deltree(p->left);
deltree(p->right);
delete p;
return NULL;
}
// Поиск узла с минимальным ключом
ttree* findMin(ttree *p) {
if (p == NULL) return NULL;
while (p->left != NULL)
p = p->left;
return p;
}
// Поиск узла с максимальным ключом
ttree* findMax(ttree *p) {
if (p == NULL) return NULL;
while (p->right != NULL)
p = p->right;
return p;
}
// Удаление узла с заданным ключом (реализация из методички)
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; // узел не найден
// Случай 1: узел не имеет дочерних узлов (лист)
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;
}
// Случай 2: только правый потомок
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;
}
// Случай 3: только левый потомок
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;
}
// Случай 4: два потомка
w = ps->left;
if (w->right == NULL) { // максимальный следует за ps
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;
}
// Построение сбалансированного дерева из отсортированного вектора
ttree* buildBalanced(vector<int> &arr, int start, int end) {
if (start > end) return NULL;
int mid = (start + end) / 2;
ttree *node = createNode(arr[mid]);
node->left = buildBalanced(arr, start, mid - 1);
node->right = buildBalanced(arr, mid + 1, end);
return node;
}
// Функция для обмена максимального и минимального ключей в дереве
void swapMinMax(ttree *root) {
if (root == NULL) return;
ttree *minNode = findMin(root);
ttree *maxNode = findMax(root);
if (minNode != NULL && maxNode != NULL && minNode != maxNode) {
int temp = minNode->inf;
minNode->inf = maxNode->inf;
maxNode->inf = temp;
}
}
int main() {
srand(time(0));
// Генерация 15 случайных уникальных чисел в диапазоне [-50, 50]
const int N = 15;
vector<int> numbers;
while (numbers.size() < N) {
int r = rand() % 101 - 50; // от -50 до 50
// чтобы избежать повторов (для простоты)
if (find(numbers.begin(), numbers.end(), r) == numbers.end())
numbers.push_back(r);
}
// Сортируем числа для построения сбалансированного дерева
sort(numbers.begin(), numbers.end());
// Строим сбалансированное дерево
ttree *root = buildBalanced(numbers, 0, numbers.size() - 1);
cout << "=== Сбалансированное дерево поиска ===\n";
cout << "Исходные числа (отсортированы): ";
for (int x : numbers) cout << x << " ";
cout << "\n\n";
cout << "Обход в порядке возрастания (симметричный): ";
inorder(root);
cout << "\n";
cout << "Прямой обход (корень-лево-право): ";
preorder(root);
cout << "\n";
cout << "Обратный обход (лево-право-корень): ";
postorder(root);
cout << "\n";
// Поиск значения (пример)
int searchKey = numbers[N/2]; // выберем средний элемент
int foundVal;
if (search(root, searchKey, foundVal))
cout << "\nПоиск: значение " << searchKey << " найдено.\n";
else
cout << "\nПоиск: значение " << searchKey << " не найдено.\n";
// Выполняем индивидуальное задание: поменять местами минимальный и максимальный ключи
cout << "\n=== Индивидуальное задание (вариант 1) ===\n";
cout << "Меняем местами минимальный и максимальный ключи.\n";
swapMinMax(root);
cout << "Дерево после обмена (обход в порядке возрастания): ";
inorder(root);
cout << "\n";
// Демонстрация удаления элемента (например, удалим число, которое было максимальным)
// Но после обмена максимальным стало бывшее минимальное. Удалим его.
// Найдём новый минимальный и максимальный для информации
ttree *newMin = findMin(root);
ttree *newMax = findMax(root);
if (newMin && newMax) {
cout << "Новый минимальный ключ: " << newMin->inf << endl;
cout << "Новый максимальный ключ: " << newMax->inf << endl;
}
// Покажем работу удаления: удалим корень (для примера)
int valToDelete = root->inf;
cout << "\nУдаляем корень со значением " << valToDelete << " ...\n";
root = dellist(root, valToDelete);
cout << "Обход после удаления: ";
inorder(root);
cout << "\n";
// Освобождение памяти
root = deltree(root);
cout << "\nПамять полностью освобождена.\n";
return 0;
}