BST Delete Leaf Node
Jun 27, 2014 at 2:05pm UTC
Hi all, i have problem with my code.
When i delete child node there isn't problem, but when i delete leaf node doesn't work, why???
Thanks all :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
using namespace std;
class tree_node
{
private :
tree_node *left;
tree_node *right;
tree_node *root;
string data;
public :
tree_node()
{
root = NULL;
}
bool isEmpty() const { return root==NULL; }
void print_inorder();
void inorder(tree_node*);
void print_preorder();
void preorder(tree_node*);
void print_postorder();
void postorder(tree_node*);
void insert(string);
void remove(string);
};
// Il più piccolo elemento va a sinitra
// L'elemento più grande va a destra
void tree_node::insert(string d)
{
tree_node* t = new tree_node;
tree_node* parent;
t->data = d;
t->left = NULL;
t->right = NULL;
parent = NULL;
// E' un nuovo nodo?
if (isEmpty()) root = t;
else
{
//Nota: tutti gli inserimenti avvengono come foglia
tree_node* curr;
curr = root;
// Trova il genitore del nodo
while (curr)
{
parent = curr;
if (t->data > curr->data) curr = curr->right;
else curr = curr->left;
}
if (t->data < parent->data)
parent->left = t;
else
parent->right = t;
}
}
void tree_node::remove(string d)
{
//Localizza l'elemento
bool found = false ;
if (isEmpty())
{
cout<<" Quest'albero è vuoto! " <<endl;
return ;
}
tree_node* curr;
tree_node* parent;
curr = root;
while (curr != NULL)
{
if (curr->data == d)
{
found = true ;
break ;
}
else
{
parent = curr;
if (d>curr->data) curr = curr->right;
else curr = curr->left;
}
}
if (!found)
{
cout<<" Campo non trovato! " <<endl;
return ;
}
// 3 casi :
// 1. Rimoviamo un nodo foglia
// 2. Rimoviamo un nodo con un singolo figlio
// 3. Rimoviamo un nodo con due figli
// Nodo con singolo figlio
if ((curr->left == NULL && curr->right != NULL)|| (curr->left != NULL
&& curr->right == NULL))
{
if (curr->left == NULL && curr->right != NULL)
{
if (parent->left == curr)
{
parent->left = curr->right;
delete curr;
}
else
{
parent->right = curr->right;
delete curr;
}
}
else // figlio sinistro presente mentre il destro no
{
if (parent->left == curr)
{
parent->left = curr->left;
delete curr;
}
else
{
parent->right = curr->left;
delete curr;
}
}
return ;
}
//Cerchiamo un nodo foglia
if ( curr->left == NULL && curr->right == NULL)
{
if (parent->left == curr) parent->left = NULL;
else parent->right = NULL;
delete curr;
return ;
}
//Nodo con 2 figli
//Riposiziona il nodo con il più piccolo valore nel sotto-albero destro
if (curr->left != NULL && curr->right != NULL)
{
tree_node* chkr;
chkr = curr->right;
if ((chkr->left == NULL) && (chkr->right == NULL))
{
curr = chkr;
delete chkr;
curr->right = NULL;
}
else //figlio destro ha figli
{
//se il figlio del nodo destro ha figli
//ci muoviamo verso sinistra per localizzare il più piccolo elemento
if ((curr->right)->left != NULL)
{
tree_node* lcurr;
tree_node* lcurrp;
lcurrp = curr->right;
lcurr = (curr->right)->left;
while (lcurr->left != NULL)
{
lcurrp = lcurr;
lcurr = lcurr->left;
}
curr->data = lcurr->data;
delete lcurr;
lcurrp->left = NULL;
}
else
{
tree_node* tmp;
tmp = curr->right;
curr->data = tmp->data;
curr->right = tmp->right;
delete tmp;
}
}
return ;
}
}
void tree_node::print_inorder()
{
inorder(root);
}
void tree_node::inorder(tree_node* p)
{
if (p != NULL)
{
if (p->left) inorder(p->left);
cout<<" " <<p->data<<" " ;
if (p->right) inorder(p->right);
}
else return ;
}
void tree_node::print_preorder()
{
preorder(root);
}
void tree_node::preorder(tree_node* p)
{
if (p != NULL)
{
cout<<" " <<p->data<<" " ;
if (p->left) preorder(p->left);
if (p->right) preorder(p->right);
}
else return ;
}
void tree_node::print_postorder()
{
postorder(root);
}
void tree_node::postorder(tree_node* p)
{
if (p != NULL)
{
if (p->left) postorder(p->left);
if (p->right) postorder(p->right);
cout<<" " <<p->data<<" " ;
}
else return ;
}
int main()
{
tree_node b;
int ch;
string tmp,tmp1;
while (1)
{
cout<<endl<<endl;
cout<<" Operazioni su Alberi Binari Di Ricerca " <<endl;
cout<<" ----------------------------- " <<endl;
cout<<" 1. Inserimento " <<endl;
cout<<" 2. In-Order " <<endl;
cout<<" 3. Pre-Order " <<endl;
cout<<" 4. Post-Order " <<endl;
cout<<" 5. Rimozione " <<endl;
cout<<" 6. Exit " <<endl;
cout<<" Inserisci la tua scelta : " ;
cin>>ch;
switch (ch)
{
case 1 : cout<<" Inserisci la stringa : " ;
cin>>tmp;
b.insert(tmp);
break ;
case 2 : cout<<endl;
cout<<" In-Order " <<endl;
cout<<" -------------------" <<endl;
b.print_inorder();
break ;
case 3 : cout<<endl;
cout<<" Pre-Order " <<endl;
cout<<" -------------------" <<endl;
b.print_preorder();
break ;
case 4 : cout<<endl;
cout<<" Post-Order " <<endl;
cout<<" --------------------" <<endl;
b.print_postorder();
break ;
case 5 : cout<<" Scegli la stringa da cancellare : " ;
cin>>tmp1;
b.remove(tmp1);
break ;
case 6 :
return 0;
}
}
}
Last edited on Jun 27, 2014 at 2:06pm UTC
Jun 27, 2014 at 4:25pm UTC
It looks to me like the code to remove a leaf is at lines 141-146 and that code looks okay to me.
However, it does appear that the code will fail if you remove the root node.
The constructor at line 16 sets
root
, but not
left
or
right
. Although your code always sets them, it's bad form to allow for the possibility of having them uninitialized. It would be handy to have a constructor that takes a string:
1 2 3
tree_node::tree_node(const string &s) :
data(s), root(NULL), left(NULL), right(NULL)
{;}
It's a little harder to understand, but the code can be greatly simplified if you use a pointer to the pointer to the current node. For example, the insert method can look like this (using the new constructor too):
1 2 3 4 5 6 7 8 9 10 11 12 13
void tree_node::insert(string d)
{
tree_node* t = new tree_node(d)
tree_node **ptr;
tree_node *curr;
for (ptr = &root; *ptr;) {
curr = *ptr;
if (t->data > curr->data) ptr = &curr->right;
else ptr = &curr->left;
}
*ptr = t;
}
Note that ptr points to one of 3 possibilities: the root pointer, a left pointer or a right pointer. The assignment at line 12 thus changes the right pointer in all 3 cases.
Topic archived. No new replies allowed.