2010-02-11 5 views
4

J'ai un BST qui est une liste liée en C++. Comment est-ce que je supprimerais le tout de la mémoire? Serait-ce fait à partir d'une fonction de classe?Comment supprimer un arbre de recherche binaire de la mémoire?

+2

Une liste chaînée a par définition des liens vers l'avant et peut-être vers l'arrière. Une BST a quitté l'enfant, l'enfant et peut-être les liens parentaux. Lequel est-ce? – Potatoswatter

+0

Mon BST a des noeuds qui peuvent avoir un enfant gauche, un enfant droit et des liens parents. – neuromancer

Répondre

1

Effectuez une traversée post-commande de l'arborescence (c'est-à-dire en visitant les enfants avant les parents) et supprimez chaque nœud lorsque vous le visitez.

Que cela ait ou non quelque chose à voir avec les classes dépend entièrement de votre implémentation.

0

Avec peu d'informations fournies ....

Si vous avez attribué les noeuds avec de nouveaux ou malloc (ou fonctions connexes) que vous devez traverser sur tous les nœuds et libres ou les supprimer.

Une alternative est de mettre shared_ptr's (and weak_ptr's to kill cyclics) dans vos allocations - à condition que vous le faites correctement, vous ne devez libérer les nœuds manuellement

Si vous avez utilisé une implémentation de la qualité que vous avez pris sur Internet que prévu la les classes ne fuient pas, vous n'avez pas à vous soucier de quoi que ce soit.

4

Il suffit de supprimer les enfants:

struct TreeNode { 
    TreeNode *l, *r, *parent; 
    Data d; 

    TreeNode(TreeNode *p) { l = nullptr; r = nullptr; parent = p; } 
    TreeNode(TreeNode const &) = delete; 
    ~TreeNode() { 
     delete l; // delete does nothing if ptr is 0 
     delete r; // or recurses if there's an object 
    } 
}; 

ou si vous utilisez unique_ptr ou un tel, qui est même pas nécessaire:

struct TreeNode { 
    unique_ptr<TreeNode> l, r; 
    TreeNode *parent; 
    Data d; 

    TreeNode(TreeNode *p) { l = nullptr; r = nullptr; parent = p; } 
    TreeNode(TreeNode const &) = delete; 
    ~TreeNode() = default; 
}; 
+0

Si vous devez conserver une partie de la sous-arborescence, vous pouvez simplement fournir une méthode Detach() qui supprimera un nœud de son parent. Ensuite, la suppression ne descendra pas dans la sous-arborescence que vous souhaitez conserver. –

+0

Avec 'auto_ptr', cela serait accompli simplement en affectant par exemple' auto_ptr outside_ptr = mon_noeud.l'. – Potatoswatter

+0

Je voudrais lever un avertissement: cet échantillon est mal et est susceptible de causer des accidents. Le problème est que l'opérateur de copie/assignation de 'auto_ptr' a une sémantique bizarre ...' const TreeNode & node = ...; TreeNode copy (noeud); node.l-> data; 'va planter (heureusement immédiatement). –

0

Utilisez des pointeurs intelligents et oublier.

3

Si vous avez accès à la liste liée elle-même, il est un morceau de gâteau:

// Making liberal assumptions about the kind of naming/coding conventions that might have been used... 
ListNode *currentNode = rootNode; 

while(currentNode != NULL) 
{ 
    ListNode *nextNode = currentNode->Next; 
    delete currentNode; 
    currentNode = nextNode; 
} 

rootNode = NULL; 

Si cela est un implemention personnalisé d'un BST, cela pourrait bien être la façon dont il fonctionne en interne, si elle a lié à une structure de données particulière.

Si vous n'avez pas accès à l'interne, la réponse de Potatoswatter devrait être sur place. En supposant que la BST est configurée comme ils le suggèrent, la simple suppression du nœud racine devrait supprimer automatiquement toute la mémoire allouée car chaque parent de l'arbre supprimera ses enfants.

Si vous demandez comment aller sur itérer à travers un arbre binaire manuellement, vous feriez l'étape récursive suivante:

void DeleteChildren(BSTNode *node) 
{ 
    // Recurse left down the tree... 
    if(node->HasLeftChild()) DeleteChildren(node->GetLeftChild()); 
    // Recurse right down the tree... 
    if(node->HasRightChild()) DeleteChildren(node->GetRightChild()); 

    // Clean up the data at this node. 
    node->ClearData(); // assume deletes internal data 

    // Free memory used by the node itself. 
    delete node; 
} 

// Call this from external code. 
DeleteChildren(rootNode); 

J'espère que je ne l'ai pas manqué le point ici et que quelque chose de ce aide.

+0

Pourquoi une fonction ClearData() serait-elle nécessaire, pourquoi ne pas supprimer le nœud? – neuromancer

+1

J'ai inclus ClearData() pour indiquer qu'à chaque nœud * quelque chose * doit être fait pour libérer la mémoire prise par les données que le nœud contient (le cas échéant) .Si le nœud a juste un pointeur vers des données externes (très probable) alors ClearData() peut simplement NULL le pointeur Si l'arbre a effectivement alloué de la mémoire pour les données elles-mêmes (disons que chaque noeud contient directement les données de chaine comme un char []) alors ClearData() devra supprimer [] ce tableau Ce que j'essayais d'impliquer, c'est que les étapes sont: 1) Effacer toutes les données détenues par chaque nœud (cela pourrait être fait dans le destructeur) 2) Supprimer le nœud lui-même. – xan

Questions connexes