Salve,ho necessità di un consiglio x migliorare il programma sotto riporato.
Mi è stato già suggerito di allocare i molti oggetti allocati dinamicamente in maniera statica; volrrei chiedervi se avete altri suggerimenti x renderlo più efficente e leggibile..
Ci tengo a precisare che il prog nn deve rispettare specifiche particolari, deve implamentare un albero binario utilizzando template e grosso modo deve effettuare le operazioni di inserimento, cancellazione, trovare max, il min ecc insomma + o- tutte quelle che ho gia definito.. Qualsiasi suggerimento è ben accetto. Grazie
------------------------------------------------------------------------------------
codice:
//main.cpp
//programma di verifica della classe Albero
#include "proj.h"
int main(){
Albero<int> P;
int v[]={47,25,11,7,17,43,31,44,77,65,68,93};
for (int i=0;i<12;i++){
P.inserisci(v[i]);
}
cout<<P;
P.MostraRadice();
P.Massimo();
P.Minimo();
P.Ricerca(7);
P.Cancella(7);
cout<<P;
P.MostraRadice();
P.Massimo();
P.Minimo();
return 0;
}
--------------------------------------------------------------------------------------
codice:
//proj.h
//Implementazione di un albero binario tramite programmazione generica[template]
#ifndef ALBEROBIN_H
#define ALBEROBIN_H
#include <iostream>
using namespace std;
template<class T>class Albero{
friend ostream& operator<<(ostream &,Albero<T>);
public:
Albero(){Radice=0; }
~Albero(){}
class Nodo{
public:
Nodo(){
sinistro=0;
destro=0;
chiave=0;
padre=0;
}
~Nodo(){}
Nodo * sinistro;
Nodo * destro;
Nodo * padre;
T chiave;
};
void inserisci(T);//inserisce un nodo nell'albero
void Massimo();//stampa il massimo
void Cancella(T);//interfaccia per la funzione cancella
void Ricerca(T);//interfaccia per la funzione ricerca
void Minimo();//stampa il minimo
void MostraRadice();//stampa la radice
void Stampa(ostream &);//utilizzata nella funzione che ridefinisce
//l'operatore << per accedere alle funzioni
//membro private
private:
//funzioni membro private
void cancella(T,Nodo **);//cancella un nodo che ha una certa chiave
bool ricerca(T,Nodo **);//ricerca un nodo che ha una certa chiave
void successore(Nodo **);//trova il successore di un nodo
void minimo(Nodo **);//scorre l'albero fino a trovare il nodo che ha chiave minore
void massimo(Nodo **);//scorre l'albero fino a trovare il nodo con chiave minore
void InOrdine(Nodo *,ostream &);//visualizza in ordine simmetrico
void PreOrdine(Nodo *,ostream &);//visualizza in ordine anticipato
void PostOrdine(Nodo *,ostream &);//visualizza in ordine posticipato
Nodo * Radice; //radice dell'albero
};
//definizione delle funzioni membro pubbliche; la classe Nodo è resa trasparente all'utente
template<class T>void Albero<T>::Massimo(){
Nodo *x=new Nodo();
x=Radice;
massimo(&x);
cout<<"La chiave di valore maggiore contenuta nell'albero e':"<<x->chiave<<endl;
}
template<class T>void Albero<T>::Cancella(T chiave){
Nodo *x=new Nodo();
x=Radice;
cout<<"Cancellazione del nodo con chiave "<<chiave<<endl;
cancella(chiave,&x);
cout<<"Nodo cancellato"<<endl;
}
template<class T>void Albero<T>::Ricerca(T chiave){
Nodo *x=new Nodo();
cout<<"Ricerca della chiave "<<chiave<<".. ";
if(ricerca(chiave,&x)) cout<<"trovata"<<endl;
else cout<<"chiave non trovata"<<endl;
}
template <class T>void Albero<T>::Minimo(){
Nodo *x=new Nodo();
x=Radice;
minimo(&x);
cout<<"La chiave minore contenuta nell'albero e': "<<x->chiave<<endl;
}
template <class T>void Albero<T>::MostraRadice(){
Nodo *x=new Nodo();
x=Radice;
cout<<"La radice dell'albero e': "<<x->chiave<<endl;
}
template <class T>void Albero<T>::Stampa(ostream &out){
out<<"Visualizzazione in Ordine Simmetrico: ";
InOrdine(Radice,out);
out<<"\nVisualizzazione in Ordine Anticipato: ";
PreOrdine(Radice,out);
out<<"\nVisualizzazione in Ordine Posticipato: ";
PostOrdine(Radice,out);
out<<endl;
}
//definizione delle funzioni membro private
template<class T>void Albero<T>::inserisci(T ChiaveDaInserire){
Nodo * y=new Nodo();
Nodo * x=new Nodo();
Nodo * z=new Nodo();
y=0;
x=0;
x=Radice;
(z->chiave)=ChiaveDaInserire;//preparazione del nodo da inserire
while (x!=0){//ricerca della corretta posizione per l'inserimento
y=x;
if((z->chiave)<(x->chiave)) x=x->sinistro;
else x=x->destro;
}
z->padre=y;
//inserzione del nodo
if (y==0) Radice=z;
else if((z->chiave)<(y->chiave)) y->sinistro=z;
else y->destro=z;
}
template<class T>void Albero<T>::cancella(T ChiaveDaCancellare,Nodo **z){
Nodo *y=new Nodo();
Nodo *x=new Nodo();
ricerca(ChiaveDaCancellare,z);//ricerca del nodo da cancellare
if(((*z)->sinistro==0)||((*z)->destro==0)) y=*z;//si determina se il nodo da
//cancellare ha figli
else {
successore(z);//se ce li ha entrambi se ne trova il successore
y=(*z);
} //che necessariamente ha un solo figlio
if(y->sinistro!=0) x=y->sinistro;
else x=y->destro;//in x si memorizza il figlio del nodo da cancellare
if(x!=0) x->padre=y->padre;//se x esiste si attacca al padre del nodo da
//cancellare
if((y->padre)==0) x=Radice;//se il nodo cancellato era la radice
//la nuova radice è x
if(y=(y->padre->sinistro)) y->padre->sinistro=x;
else y->padre->destro=x;//se il nodo cancellato era il figlio sinistro/destro
//si aggiorna il puntatore sinistro/destro
if(y!=(*z)) (*z)->chiave=y->chiave;//se il nodo da cancellare ha richiesto
//la determinazione del successore copia la chiave
//del successore
(*z)=y;//restituisce il nodo cancellato
}
template<class T>bool Albero<T>::ricerca(T ChiaveDaRicercare,Nodo **x){//ricerca iterativa
*x=Radice;//partiamo dalla radice si scorre l'albero fino a trovare la chiave
while(((*x)!=0)&&((*x)->chiave!=ChiaveDaRicercare)){
if(ChiaveDaRicercare<((*x)->chiave)) *x=(*x)->sinistro;
else (*x)=(*x)->destro;
}
if((*x)!=0)return true;
else return false;
}
template<class T>void Albero<T>::successore(Nodo **x){
Nodo *y=new Nodo();
if((*x)->destro!=0){
minimo(&((*x)->destro));//se il nodo ha figlio destro il successore
return; //coincide con il nodo minimo del sottoalbero
} //destro
y=(*x)->padre;//se non ha un figlio destro
while((y!=0)&&((*x)=y->destro)){
(*x)=y; //si risale gli antenati di x fino a trovare il nodo
y=(*x)->padre;//antenato meno lontano e più piccolo
}
(*x)=y;
}
//dato un nodo ne discende tutti i figli alla sinistra fino a trovare il minimo
template<class T>void Albero<T>::minimo(Nodo **x){
while(((*x)->sinistro)!=0) {(*x)=(*x)->sinistro;}
}
//dato un nodo ne discende tutti i figli alla destra fino a trovare il massimo
template<class T>void Albero<T>::massimo(Nodo **x){
while(((*x)->destro)!=0) {(*x)=(*x)->destro;}
}
//visualizzazzione dei nodi
template<class T>void Albero<T>::InOrdine(Nodo *x,ostream &out){
if (x!=0) {
InOrdine(x->sinistro,out);
out<<(x->chiave)<<" ";
InOrdine(x->destro,out);
}
}
template<class T>void Albero<T>::PreOrdine(Nodo *x,ostream &out){
if (x!=0) {
out<<(x->chiave)<<" ";
PreOrdine(x->sinistro,out);
PreOrdine(x->destro,out);
}
}
template<class T>void Albero<T>::PostOrdine(Nodo *x,ostream &out){
if (x!=0) {
PostOrdine(x->sinistro,out);
PostOrdine(x->destro,out);
out<<(x->chiave)<<" ";
}
}
//definizione della classe friend che effettua una ridefinizione dell'operatore << e permette
//dato un albero la stampa dei suoi elementi in ordine anticipato simmetrico e posticipato
template <class T> ostream& operator<<(ostream &out,Albero<T> A){
out<<"##########Visualizzazione dei nodi##########\n";
A.Stampa(out);
return out;
}
#endif