implementazione BST
-
20-09-2019 - |
Domanda
Cosa c'è di sbagliato con la seguente implementazione di un ricerca binaria albero (BST) ? Mi è stato detto che è meglio usare il puntatore a un puntatore a struct
nodo come un argomento in funzione di inserimento.
struct node
{
int key_value;
struct node* left;
struct node* right;
};
insert(int key, struct node *leaf)
{
if( leaf == 0 )
{
leaf = (struct node*) malloc( sizeof( struct node ) );
leaf->key_value = key;
/* initialize the children to null */
leaf->left = 0;
leaf->right = 0;
}
else if(key < leaf->key_value)
{
insert( key, leaf->left );
}
else if(key > leaf->key_value)
{
insert( key, leaf->right );
}
}
Soluzione
Questa riga:
leaf = (struct node*) malloc( sizeof( struct node ) );
dà un nuovo valore per leaf
, puntando ad un certo memoria appena allocata. Tuttavia, il nuovo valore non lascia la funzione. Quando la funzione ritorna, il chiamante sarà ancora riferimento al vecchio leaf
, e ci sarà una perdita di memoria.
Ci sono due approcci si potrebbe adottare per risolverlo:
1. Utilizzare un puntatore a un puntatore, per es.
void insert(int key, struct node **leaf)
{
if(*leaf == 0 )
{
*leaf = (struct node*) malloc( sizeof( struct node ) );
...
}
/* In caller -- & is prepended to current_leaf. */
insert(37, ¤t_leaf);
2. Riportare la nuova foglia (o il vecchio foglia se non v'è nessun cambiamento).
struct node *insert(int key, struct node *leaf)
{
if(leaf == 0 )
{
leaf = (struct node*) malloc( sizeof( struct node ) );
...
}
return leaf;
}
/* In caller -- & is prepended to current_leaf. */
current_leaf = insert(37, current_leaf);
puntatori a puntatori sono vicino alla soglia di essere difficile da comprendere. Io probabilmente andare per la seconda opzione, se insert
non è attualmente tornando qualsiasi altra cosa.
Altri suggerimenti
Quando un nodo viene inserito (foglia == 0), non ha cambiato il suo genitore, in modo che il nuovo nodo diventerà orfano.
In altre parole, il vostro albero sarà ancora l'aspetto di un solo nodo, indipendentemente dal numero di nodi sono stati chiamati con inserto.
#include<stdio.h>
typedef struct tnode{
int data;
struct tnode *left,*right;
}TNODE;
TNODE * createTNode(int key){
TNODE *nnode;
nnode=(TNODE *)malloc(sizeof(TNODE));
nnode->data=key;
nnode->left=NULL;
nnode->right=NULL;
return nnode;
}
TNODE * insertBST(TNODE *root,int key){
TNODE *nnode,*parent,*temp;
temp=root;
while(temp){
parent=temp;
if(temp->data > key)
temp=temp->left;
else
temp=temp->right;
}
nnode=createTNode(key);
if(root==NULL)
root=nnode;
else if(parent->data>key)
parent->left=nnode;
else
parent->right=nnode;
return root;
}
void preorder(TNODE *root){
if(root){
printf("%5d",root->data);
preorder(root->left);
preorder(root->right);
}
}
void inorder(TNODE *root){
if(root){
inorder(root->left);
printf("%5d",root->data);
inorder(root->right);
}
}
void postorder(TNODE *root){
if(root){
postorder(root->left);
postorder(root->right);
printf("%5d",root->data);
}
}
main(){
TNODE *root=NULL;
int ch,key;
do{
printf("\n\n1-Insert\t2-Preorder\n3-Inorder\t4-Postorder\n5-Exit\n");
printf("Enter Your Choice: ");
scanf("%d",&ch);
switch(ch){
case 1:
printf("Enter Element: ");
scanf("%d",&key);
root=insertBST(root,key);
break;
case 2:
preorder(root);
break;
case 3:
inorder(root);
break;
case 4:
postorder(root);
break;
default:
printf("\nWrong Choice!!");
}
}while(ch!=5);
getch();
return 0;
}