Узел не удаляется из двоичного дерева поиска C

#c #binary-search-tree

#c #binary-search-tree

Вопрос:

Я продолжаю пытаться удалить 25 из дерева и не могу удалить его. Я пробовал отлаживать и создавать точки останова и все, ничего не работает. Я не кодировал так уже больше года, и это оказалось очень непросто.

Пожалуйста, помогите!

![вывод] (https://i.gyazo.com/8e953ebe14d9d33a2a0ffa233ccfacb1.png )

 #ifndef BSTREE_H
#define BSTREE_H
#include <iostream>
#include <iomanip>
using namespace std;

// class must be templated
template <class DataType>
class BSTree
{
private:
// You may NOT add any data members
struct node;
typedef node* nodePtr;

struct node
{
    DataType element;
    nodePtr right;
    nodePtr left;
};
int count;
nodePtr root;

// You may add any private member functions here
bool isEmpty() // helper funtion for determining if the tree is empty
{
    return root == NULL;
}

void inOrderPrint(nodePtr x, ostreamamp; out)
{
    if (root != NULL)
    {
        inOrderPrint(x->left, out);
        out << x->element << " ";
        inOrderPrint(x->right, out);
    }
}

void preOrderPrint(nodePtr x, ostreamamp; out)
{
    if (root != NULL)
    {
        out << x->element << " ";
        preOrderPrint(x->left, out);
        preOrderPrint(x->right, out);
    }
}

bool search(DataType x) // helper function to check if item is in tree already
{
    bool found = false;
    if (isEmpty())
    {
        cout << "Nothing in the Tree!" << std::endl;
        return false;
    }
    nodePtr current;
    nodePtr parent;
    current = root;
    parent = NULL;
    while (current != NULL)
    {
        if (current->element == x)
        {
            found = true;
            break;
        }
        else
        {
            //parent = current;
            if (x > current->element)
            {
                current = current->right;
            }
            else
            {
                current = current->left;
            }
        }
    }
    if (!found)
    {
        found = false;
    }
    else
    {
        found = true;
    }
    return found;

}

/*
nodePtr findNode(nodePtr x)
{
    bool found = false;
    if (isEmpty())
    {
        cout << "Nothing in the Tree!" << std::endl;
        return;
    }
    nodePtr current;
    nodePtr parent;
    current = root;
    parent = NULL;
    while (current != NULL)
    {
        if (current->element == x->element)
        {
            found = true;
            return x;
            break;
        }
        else
        {
            parent = current;
            if (x->element > current->element)
            {
                current = current->right;
            }
            else
            {
                current = current->left;
            }
        }
    }
    if (!found)
    {
        found = false;
        return;
    }
    else
    {
        found = true;
    }
    return x;

}
*/

void destroyTree(nodePtr x)
{
    if (x != NULL)
    {
        destroyTree(x->left);
        destroyTree(x->right);
        delete x;
    }
}

// This method is given – it is called by printTree
void printTreeHelper(int depth, nodePtr cur) const
{
    const int spacing = 4;
    if (cur != NULL)
    {
        if (depth == 0)
            cout << cur->element;
        else
            cout << setw(spacing * depth) << " " << cur->element;
        cout << endl;
        printTreeHelper(depth   1, cur->right);
        printTreeHelper(depth   1, cur->left);
    }
    else
        cout << setw(spacing * depth) << " " << "****" << endl;

}

void copyTreeHelper(nodePtr x)
{
    if (x != NULL)
    {
        insert(x->element);
        copyTreeHelper(x->left);
        copyTreeHelper(x->right);
    }
}

nodePtr minNodeFinder(nodePtr min)
{
    nodePtr curr = min;
    while ((curr != NULL) amp;amp; (curr->left != NULL))
    {
        curr = curr->left;
    }
    return curr;
}

public:
// Default constructor
BSTree()
{
    root = NULL;
}

// Copy constructor
BSTree(const BSTree<DataType>amp; copyTree)
{
    root = NULL;
    copyTreeHelper(copyTree.root);
}

// Equal overload
const BSTreeamp; operator =(const BSTreeamp; rhs)
{
    if (this == amp;rhs)
    {
        return *this;
    }
    else
    {
        copyTreeHelper(rhs.root);
        deleteTree();
        return *this;
    }
}

// Destructor
~BSTree()
{
    deleteTree();
}

// Inserts element into the tree
// If value is already in the tree do NOt add it
// a second time
void insert(DataType x)
{
    if (search(x))
    {
        cout << "item already in tree" << std::endl;

    }
    else
    {
        nodePtr temp = new node();
        nodePtr parent;
        temp->element = x;
        temp->left = NULL;
        temp->right = NULL;
        parent = NULL;
        if (isEmpty())
        {
            root = temp;
        }
        else
        {
            nodePtr current;
            current = root;
            while (current)
            {
                parent = current;
                if (temp->element > current->element)
                {
                    current = current->right;
                }
                else
                {
                    current = current->left;
                }
            }
            if (temp->element < parent->element)
            {
                parent->left = temp;
            }
            else
            {
                parent->right = temp;
            }
        }
    }
}

//Print the tree as a tree
// This (and its helper function) is given to you
// See sample output and understand how the tree is displayed
// because it can help when testing the code
bool printTree() const
{
    if (root == NULL)
        return false;
    else
    {
        printTreeHelper(0, root);
        return true;
    }
}

// Prints tree in order to the screen
// call printInOrder with  cout passed in
// This function is done for you
void printInOrder()
{
    printInOrder(cout);
}

// Prints the tree in order to
// the ostream passed into it
void printInOrder(ostreamamp; out)
{
    inOrderPrint(root, out);
    out << std::endl;
}

// Prints tree in preorder to the screen
// call printPreOrder with  cout passed in
// This function is done for you
void printPreOrder()
{
    printPreOrder(cout);
}
// Prints the tree in preorder to
// the ostream passed into it
void printPreOrder(ostreamamp; out)
{
    preOrderPrint(root, out);
    out << std::endl;
}

// Deletes the item passed in from the tree
// It returns a true if it finds it and deletes it, otherwise
// It returns a false
bool  deleteNode(DataType x)
{
    
    if (!search(x))
    {
        cout << "Item not found" << std::endl;
        return false;
    }
    nodePtr current;
    nodePtr parent;
    current = root;
    parent = NULL;
    //Node is a single node with one child
    if((current->left == NULL amp;amp; current->right != NULL) ||
       (current->left != NULL amp;amp; current->right == NULL))
    {
        if(current->left == NULL amp;amp; current->right != NULL) // right child is present
        {
            if(parent->left == current)
            {
                parent->left = current->right;
                delete current;
            }
            else
            {
                parent->right = current->right;
                delete current;
            }
        }
        else // left child is present
        {
            if (parent->left == current)
            {
                parent->left = current->left;
                delete current;
            }
            else
            {
                parent->right = current->left;
                delete current;
            }
        }
        return true;
    }
    // node is a leaf node
    if (current->left == NULL amp;amp; current->right == NULL)
    {
        if(parent == NULL)
        {
            delete current;
        }
        else
        {
            if(parent->left == current)
            {
                parent->left = NULL;
            }
            else
            {
                parent->right = NULL;
            }
            delete current;
            return true;
        }
    }
    // node has two children i.e parent node
    if (current->left != NULL amp;amp; current->right != NULL)
    {
        nodePtr checker;
        checker = current->right;
        if ((checker->left == NULL) amp;amp; (current->right == NULL))
        {
            current = checker;
            delete current;
            current->right = NULL;
        }
        else // right child has children
        {
            //nodes right child has a left child
            if ((current->right)->left != NULL)
            {
                nodePtr left_current;
                nodePtr left_current_parent;
                left_current_parent = current->right;
                left_current = (current->right)->left;
                while (left_current->left != NULL)
                {
                    left_current_parent = left_current;
                    left_current = left_current->left;
                }
                current->element = left_current->element;
                delete left_current;
                left_current_parent->left = NULL;
            }
            else
            {
                nodePtr temp;
                temp = current->right;
                current->element = temp->element;
                current->right = temp->right;
                delete temp;
            }
        }
    }
    return true;
}

// Deletes the item passed in from the tree
// It also passes back the item to the calling function
// It returns a true if it finds it and deletes it, otherwise
// It returns a false
bool  deleteNodePassBackData(DataType x, DataTypeamp; temp)
{
    if (search(x))
    {
        nodePtr itemToDelete = findNode(x);
        temp = itemToDelete->element;
        deleteNode(x);
        return true;
    }
    else
    {
        return false;
    }
}

// Deletes the whole tree
void deleteTree()
{
    destroyTree(root);
}
};

#endif


     BSTree<int> t1;
  t1.insert(50);
  t1.insert(75);
  t1.insert(25);
  t1.insert(22);
  t1.insert(5);
  t1.insert(85);
  t1.insert(95);
  t1.insert(82);
  t1.insert(76);
  t1.printTree();

  BSTree<int> t2(t1);
  t2.deleteNode(25);
  t2.deleteNode(75);
  t2.deleteNode(50);
  
  cout << "After copy constructor and deletes" << endl;
  cout << "T1" << endl;
  t1.printTree();
  cout << "T2" << endl;
  t2.printTree();
  

Ответ №1:

Прежде всего, вы всегда должны публиковать полный код для отладки кем-то другим. Если я не могу запустить ваш код, как я вообще могу его отладить?

Но помимо этого, deleteNode(DataType x) в вашем коде есть серьезная проблема.
current НИКОГДА НЕ ПРОХОДИТЕ по дереву вообще.
deleteNode() функция всегда будет удалять корень дерева, если элемент существует в дереве.

Вы должны перемещаться по дереву, как вы делали в search() функции внутри deleteNode() функции.

Кстати, в чем смысл приведенного ниже кода search() ?

 if (!found)
{
    found = false;
}
else
{
    found = true;
}
  

Комментарии:

1. Повторно загружен со всем кодом. Честно говоря, я не уверен. я не кодировал на C почти год, и он очень ржавый. Это для моего класса algorihims, и она сказала, что мы вообще не можем изменять функции