Ошибка Seg в моей операции удаления в C ++

0

Я пишу код для назначения c++, это реализация словаря, использующая двоичное дерево поиска. Мой код компилируется, но когда я пытаюсь "удалить", я получаю seg Fault. любые идеи, почему это могло произойти. благодаря

Вот мой код

// this function calls the deleteNode function where the deletion is done
void BST::deleteContent(string *word)
{
    deleteNode(word, root);
}
// a helper fuuntion for the deletecontent function
//uses recursion to find the node to be deleted
void BST::deleteNode(const string *word, Node *&nodePtr)
{
    if(word < nodePtr->word)
        deleteNode(word, nodePtr->left);
    else if(word > nodePtr->word)
        deleteNode(word, nodePtr->right);
    else
        makeDeletion(nodePtr);
}
// a helper function for the deleteNode function
void BST::makeDeletion(Node *&nodePtr)
{
    Node *tempNodePtr;

    if(nodePtr == NULL)
        cout<< "cannot delete empty node. \n";
    // if node has no right child
    else if (nodePtr->right == NULL)
        {
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->left; // reattach child
            delete tempNodePtr;
        }
    else if(nodePtr-> left == NULL)
        {
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->right; // reattach child
            delete tempNodePtr;
        }
    // if node has 2 children
    else
        {
            tempNodePtr = nodePtr->right;
            while (tempNodePtr->left)
                tempNodePtr = tempNodePtr->left;
            tempNodePtr->left = nodePtr->left;
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->right;
            delete tempNodePtr;
        }
}

EDIT:

Спасибо вам всем!! С вашего поста я понял, что было хорошей идеей проверить, был ли узел последним и детей не было. Я добавил эту проверку в deleteNode

    if((nodePtr->left) && word < nodePtr->word)
    {
        do something
    }

я сделал то же самое для правильной работы, и не делал никаких ошибок или сбоев. Спасибо!!!!

  • 0
    Если удаляемого слова нет в дереве, вы вернетесь в нулевой узел. Затем, когда вы попытаетесь выполнить nodePtr->word , вы будете разыменовывать нулевой указатель.
  • 1
    включите coredump и посмотрите на обратную трассировку. перед удалением чека на ноль и распечатки
Показать ещё 3 комментария
Теги:
dictionary
binary-search-tree

1 ответ

1

Случай 1: Пустое дерево:

Предположим, что ваше дерево пуст: root будет nullptr. Так deleteContent() будем называть deleteNode() с аргументом nullptr для nodePtr.

Первое, что вы есть сравнить word с nodePtr->word без первой проверки, что nodePtr не nullptr. У вас есть первый случай скрещивания!

Случай 2: удалите слово, которое не находится в дереве:

В этом случае deleteNode() будет вызываться рекурсивно до тех пор, пока не достигнет листового узла без потомка. Поскольку искомое слово не существует в дереве, оно либо имеет значение, либо меньшее, чем nodePtr-> слово, но никогда не равнозначно. deleteNode() будет называть себя, снова передавая аргумент nullptr для nodePtr, как и в случае 1. Опять же, вы будете иметь ошибку сегментации!

Решение в случае 1 и 2: управление nullptr в deleteNode():

void BST::deleteNode(const string *word, Node *&nodePtr)
{
    if (nodePtr==nullptr) 
        cout << word << " not found in the tree\n";
    else if (word < nodePtr->word)
        ...   // the rest as in your original function 
}

makeDeletion() теперь должен вызываться методом deleteNode() тогда и только тогда, когда nodePtr не является нулевым, а word==nodePtr->word. Избавьтесь от первого if(), которое в любом случае не должно быть истинным. Может быть заменено его утверждением при проверке инварианта.

Случай 3: Удалить слово в дереве:

Кажется, что все три случая работают (даже листовые узлы с двумя нулевыми указателями), по крайней мере, если я посмотрю на мой рисунок вашей структуры данных.

Однако я хотел бы предложить, чтобы проверить Node::~Node(): во всех случаях, вы прикрутите ребенок, а затем удалить старый узел (temNodePtr), не поставив свои ребенок nullptr. Поэтому я задаюсь вопросом, просто ли ~Node() просто разрушает узел, не заботясь о его дочерних makeDeletion() (тогда makeDeletion() должен работать) или если его рекурсивный деструктор, удалив узел и его дочерние makeDeletion() тогда makeDeletion() не будет работать, потому что вы удалит узлы, которые вы только что подключили, не заметив их, создав вначале seg.fault).

Кстати, nullptr может быть более подходящим, чем NULL для указателей, даже если NULL будет работать правильно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню