Возникает ошибка "Вызвано исключение: нарушение доступа для чтения"

 #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;
}
→ Ссылка