Eliminación del árbol de búsqueda binaria (método Inorder Pred) C ++

votos
1

Ok, entonces pensé que estaba arreglado, pero obtengo resultados totalmente inconsistentes. Lo reescribí desde cero para comenzar de nuevo y aquí están mis resultados. No recibo errores, no choco, simplemente no los elimina. Simplemente arruina totalmente el árbol y me da un montón más de hojas, y lo mezcla todo. No estoy seguro de a dónde ir

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;
    }
Publicado el 29/10/2008 a las 05:56
fuente por usuario
En otros idiomas...                            


3 respuestas

votos
0

No debería llamar de manera remove()recursiva en el tercer caso (donde su comentario "no estoy seguro si esto es correcto"). En el caso en que el nodo para eliminar tenga dos hijos, lo que desea hacer es encontrar el hijo más a la derecha del hijo izquierdo (como lo está haciendo, el nodo resultante se almacena en parent). Este nodo no tiene un hijo correcto: haga que su hijo correcto sea el hijo correcto del nodo que se eliminará. Luego simplemente cambie la rootvariable para que sea su hijo izquierdo; no es necesario cambiar el datamiembro en ningún nodo o llamar de forma removerecursiva.

En fotos:

Antes de:
         r <- puntos raíz aquí
       / \
      / \
     ab
    / \ / \
   xcyy
      / \
     xd
        /
       X

Después:
      a <- puntos raíz aquí
     / \
    xc
       / \
      xd
         / \
        xb
           / \
          yy
Respondida el 29/10/2008 a las 06:22
fuente por usuario

votos
0

¿Cada T se encuentra en el árbol único? Parece que son de tu código ...

Parece que esto debería funcionar:

En el caso else, eliminar el nodo raíz:

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;
Respondida el 29/10/2008 a las 06:57
fuente por usuario

votos
1

Lo que en realidad estaba sucediendo es que las búsquedas podrían invertirse, por lo que en realidad seguirían funcionando correctamente, pero los datos no coincidían correctamente y, por lo que parece, golpearían una pared.

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

debería haber sido

if(x < root->data)
remove(root->left, x);
else
remove(root->right, x);
Respondida el 29/10/2008 a las 08:09
fuente por usuario

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