Возникает ошибка "Вызвано исключение: нарушение доступа для чтения"
#include <iostream>
#include <cstdlib>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
Node(int value) {
data = value;
left = nullptr;
right = nullptr;
}
};
class BinarySearchTree {
public:
Node* root;
public:
BinarySearchTree() {
root = nullptr;
}
// Метод для добавления элемента в дерево
void insert(int value) {
root = insertRec(root, value);
}
// Рекурсивная функция для вставки узла в дерево
Node* insertRec(Node* root, int value) {
if (root == nullptr) {
return new Node(value);
}
if (value < root->data) {
root->left = insertRec(root->left, value);
}
else if (value > root->data) {
root->right = insertRec(root->right, value);
}
return root;
}
// Метод для обхода дерева (в данном случае использован прямой обход: корень -> левое поддерево -> правое поддерево)
void preOrderTraversal(Node* root) {
if (root == nullptr) {
return;
}
cout << root->data << " ";
preOrderTraversal(root->left);
preOrderTraversal(root->right);
}
// Метод для поиска элемента в дереве
bool search(Node* root, int key) {
if (root == nullptr) {
return false;
}
if (root->data == key) {
return true;
}
if (key < root->data) {
return search(root->left, key);
}
else {
return search(root->right, key);
}
}
// Метод для подсчета количества узлов в дереве (рекурсивный обход)
int countNodes(Node* root) {
if (root == nullptr) {
return 0;
}
return 1 + countNodes(root->left) + countNodes(root->right);
}
// Метод для подсчета количества листьев в дереве (рекурсивный обход)
int countLeaves(Node* root) {
if (root == nullptr) {
return 0;
}
if (root->left == nullptr && root->right == nullptr) {
return 1;
}
return countLeaves(root->left) + countLeaves(root->right);
}
// Метод для нахождения степени узла (количество потомков)
int degreeOfNode(Node* root, int key) {
if (root == nullptr) {
return -1; // Узел не найден - возвращаем -1
}
if (root->data == key) {
int degree = 0;
if (root->left != nullptr) degree++;
if (root->right != nullptr) degree++;
return degree;
}
int leftDegree = degreeOfNode(root->left, key);
if (leftDegree != -1) {
return leftDegree;
}
return degreeOfNode(root->right, key);
}
// Метод для нахождения уровня узла в дереве
int levelOfNode(Node* root, int key, int level) {
if (root == nullptr) {
return -1; // Узел не найден - возвращаем -1
}
if (root->data == key) {
return level;
}
int leftLevel = levelOfNode(root->left, key, level + 1);
if (leftLevel != -1) {
return leftLevel;
}
return levelOfNode(root->right, key, level + 1);
}
// Метод для поиска образца в дереве
bool findPattern(Node* root, int pattern) {
if (root == nullptr) {
return false;
}
if (root->data == pattern) {
return true;
}
return findPattern(root->left, pattern) || findPattern(root->right, pattern);
}
// Метод для удаления узла дерева с поддеревом
Node* removeNodeWithSubtree(Node* root, int key) {
if (root == nullptr) {
return root;
}
if (key < root->data) {
root->left = removeNodeWithSubtree(root->left, key);
}
else if (key > root->data) {
root->right = removeNodeWithSubtree(root->right, key);
}
else {
if (root->left == nullptr) {
Node* temp = root->right;
delete root;
return temp;
}
else if (root->right == nullptr) {
Node* temp = root->left;
delete root;
return temp;
}
Node* temp = minValueNode(root->right);
root->data = temp->data;
root->right = removeNodeWithSubtree(root->right, temp->data);
}
return root;
}
Node* minValueNode(Node* node) {
Node* current = node;
while (current->left != nullptr) {
current = current->left;
}
return current;
}
// Метод для удаления всего дерева
void deleteTree(Node* root) {
if (root == nullptr) {
return;
}
deleteTree(root->left);
deleteTree(root->right);
delete root;
}
// Метод для удаления узла с перестройкой дерева
Node* removeNodeWithRebuilding(Node* root, int key) {
if (root == nullptr) {
return nullptr;
}
if (key < root->data) {
root->left = removeNodeWithRebuilding(root->left, key);
}
else if (key > root->data) {
root->right = removeNodeWithRebuilding(root->right, key);
}
else {
if (root->left == nullptr) {
Node* temp = root->right;
delete root;
return temp;
}
else if (root->right == nullptr) {
Node* temp = root->left;
delete root;
return temp;
}
else {
Node* temp = minValueNode(root->right);
root->data = temp->data;
root->right = removeNodeWithRebuilding(root->right, temp->data);
}
}
return root;
}
};
int main() {
setlocale(LC_ALL, "rus");
BinarySearchTree bst;
// Добавление элементов
int n;
cout << "Введите количество элементов для дерева: ";
cin >> n;
for (int i = 0; i < n; i++) {
int value = rand() % 100; // Добавляем случайные значения от 0 до 99
bst.insert(value);
}
// Вывод дерева
cout << "Прямой обход дерева (корень -> левое поддерево -> правое поддерево): ";
bst.preOrderTraversal(bst.root);
cout << endl;
int choice;
do {
cout << "Выберите действие:" << endl;
cout << "1. Добавление узла в бинарное дерево" << endl;
cout << "2. Вывод бинарного дерева" << endl;
cout << "3. Поиск образца в бинарном дереве" << endl;
cout << "4. Подсчет количества узлов дерева" << endl;
cout << "5. Подсчет числа листьев дерева" << endl;
cout << "6. Удаление узла дерева с поддеревом" << endl;
cout << "7. Удаление всего дерева" << endl;
cout << "8. Удаление узла с перестройкой дерева" << endl;
cout << "0. Выход" << endl;
cout << "Ваш выбор: ";
cin >> choice;
int value, key;
bool found;
switch (choice) {
case 1:
cout << "Введите значение для добавления: ";
cin >> value;
bst.insert(value);
break;
case 2:
cout << "Прямой обход бинарного дерева: ";
bst.preOrderTraversal(bst.root);
cout << endl;
break;
case 3:
cout << "Введите образец для поиска: ";
cin >> key;
found = bst.findPattern(bst.root, key);
if (found) {
cout << "Образец найден!" << endl;
}
else {
cout << "Образец не найден!" << endl;
}
break;
case 4:
cout << "Количество узлов в дереве: " << bst.countNodes(bst.root) << endl;
break;
case 5:
cout << "Количество листьев в дереве: " << bst.countLeaves(bst.root) << endl;
break;
case 6:
cout << "Введите значение для удаления с поддеревом: ";
cin >> value;
bst.removeNodeWithSubtree(bst.root, value);
break;
case 7:
bst.deleteTree(bst.root);
cout << "Дерево удалено" << endl;
break;
case 8:
cout << "Введите значение для удаления с перестройкой: ";
cin >> value;
bst.removeNodeWithRebuilding(bst.root, value);
break;
case 0:
cout << "Выход из программы" << endl;
break;
default:
cout << "Некорректный выбор!" << endl;
}
} while (choice != 0);
return 0;
}
Программа создаёт бинарное дерево из n элементов. Дерево заполняется случайными элементами. После удаления всего дерева, при попытке вывести дерево, возникает ошибка, по идее, пользователь должен перенаправляться обратно в меню выбора операций.
Почему возникает ошибка? Я вроде предусмотрела ситуацию, когда дерево пустое. Как можно исправить, подскажите, пожалуйста? Пыталась разобраться сама, просидела весь день
Ответы (1 шт):
Автор решения: Igoryao
→ Ссылка
Я нашел такое решение: требуется модификация метода полной очистки дерева.
Поскольку при выводе вы проверяете значение на nullptr, то нужно присвоить его корню. Также не забудьте передать ссылку на указатель (Node*&) для модификации указателя в методе.
void deleteTree(Node*& root) {
if (root == nullptr) {
return;
}
deleteTree(root->left);
deleteTree(root->right);
delete root;
root = nullptr;
}