Двоичное дерево Удаление (метод Симметричного Pred) C ++

голоса
1

Хорошо, таким образом я думал, что это было зафиксировано, но я получаю совершенно противоречивые результаты. Я переписал его вид с нуля, чтобы начать заново, и вот мои результаты. Я не получаю ошибки, не треск, он просто не удаляет их. Это просто совершенно портит дерево и дает мне тонну больше листьев, и смешивает все. Не уверен, куда еще пойти

template <class T>
void BST<T>::remove(struct Node<T>*& root, const T& x)
{
   Node<T>* ptr = root;
   bool found = false;
   Node<T>* parent;


   while (ptr != NULL && !found)
   {
       if (x < ptr->data)
       {
           parent = ptr;
           ptr = ptr->left;
       }
       else if (x > ptr->data)
       {
           parent = ptr;
           ptr = ptr->right;
       }
       else
           found = true;
   }

   if (found == false)
       return;
   else
   {
       if(ptr->left != NULL && ptr->right != NULL)
       {
           Node<T>* inOrderPtr = ptr->left;
           parent = ptr;
           while (inOrderPtr->right != NULL)
           {
               parent = inOrderPtr;
               inOrderPtr = inOrderPtr->right;
           }

           ptr->data = inOrderPtr->data;
           ptr = inOrderPtr;
       }
    Node<T>* subPtr = ptr->left;
    if (subPtr == NULL)
        subPtr = ptr->right;

    else if (parent->left == ptr)
        parent->left = subPtr;

    else
        parent->right = subPtr;

    delete ptr;
    }
Задан 29/10/2008 в 05:56
источник пользователем
На других языках...                            


3 ответов

голоса
0

Вы не должны называть remove()рекурсивно в третьем случае (когда ваш «не уверен, что это правильно» комментарий). В случае , когда узел для удаления имеет два детей, что вы хотите сделать , это найти самый правый ребенка левого ребенка (как вы делаете, полученный узел хранятся в parent). Этот узел не имеет права ребенка - это сделать так , что его право ребенка является право ребенка узла, подлежащего удалению. Тогда просто изменить rootпеременную , чтобы быть его левым потомком; Нет необходимости менять dataэлемент в любых узлах или вызвать removeрекурсивно.

На снимках:

До:
         г <- корневые точки здесь
       / \
      / \
     аб
    / \ / \
   xcyy
      / \
     XD
        /
       Икс

После:
      а <- корневые точки здесь
     / \
    хс
       / \
      XD
         / \
        XB
           / \
          уу
Ответил 29/10/2008 в 06:22
источник пользователем

голоса
0

Каждый из T найти в дереве уникального? Похоже, что они из вашего кода ...

Похоже, что это должно работать:

В остальном случае удаление корневого узла:

Node<T> *tmp_r = root->left;
Node<T> *parent = root;
while (tmp_r->right != NULL)
{
    parent = tmp_r;
    tmp_r = tmp_r->right;
}
Node<T> *tmp_l = tmp_r;
while (tmp_l->left != NULL)
    tmp_l = tmp_l->left;

tmp_l->left = root->left;
tmp_r->right = root->right;
parent->right = NULL;

parent = root;
root = tmp_r;
delete parent;
Ответил 29/10/2008 в 06:57
источник пользователем

голоса
1

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

if (root->data < x)
        remove(root->left, x);
    else 
        remove(root->right, x);

должно было

if(x < root->data)
remove(root->left, x);
else
remove(root->right, x);
Ответил 29/10/2008 в 08:09
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more