PDA

View Full Version : HELP ME.............. :(


alessia86
02-12-2008, 12:18
Spero che qualcuno mi aiuti perchè sto davv impazzendo :muro:
Allora il mio problema è questo devo creare un albero di caratteri partendo dal seguente vettore v[]=[s, t, u ,d ,i, a ,r ,e] devo creare il seguente albero
“studiare”
“stud” “iare”
“st” “ud” “ia” “re”
“s” “t” “u” “d” “i” “a” “r” “e”
che presenta come foglie i caratteri contenuti nel vettore v,ed il contenuto informativo ad un generico livello i è ottenuto concatenando le stringhe presenti nei suoi nodi figli.

La funz che ho fatto io è la seguente:

void costruisci(AlberoB<char*> & A,char* v[n])
{
Coda<char*> c;
for(int i=0;i<n;i++)
c.inCoda(v[i]);
char S1[80];
char* completo="studiare";
while(!c.vuota() && strcmp(S1,completo)!=0 ){
char S2[80];

strcpy(S1,c.fuoriCoda());
strcpy(S2,c.fuoriCoda());

char S[80];
strcpy(S,S1);

AlberoB<char*> B(S);
AlberoB<char*> C(S2);

strcat(S1,S2);
c1.inCoda(S1);

A.modRadice(S1);
A.insFiglio(SIN,B);
A.insFiglio(DES,C);

}
stampa(A);

}


void stampa(AlberoB<char*> A)
{
if(!A.nullo())
{
cout<<A.radice()<<endl;

stampa(A.figlio(SIN));
stampa(A.figlio(DES));
}

}


Il problema è che nella coda c mi memorizza s,t,u,d,i,a,r,e; ma quando faccio la concatenazione non me li salva nella coda,ma mi ci mette re,re,re,re
ed invece dovrebbe salvarci: st,ud,ia,re,stud,iare,ed infine studiare.
Spero che qualcuno mi aiuta non so davvero come fare :doh:

banryu79
02-12-2008, 13:21
Un consiglio: posta il codice tra i tag "CODE" così non si perde l'identazione, e identalo in modo leggibile. In questo modo è più probabile che l'eventuale lettore si prenda la briga di controllare il tuo sorgente (io per esempio, i codici non pubblicati tra i tag appositi non li guardo neanche).

alessia86
02-12-2008, 14:47
void costruisci(AlberoB<char*> & A,char* v[n])
{
Coda<char*> c;
for(int i=0;i<n;i++)
c.inCoda(v[i]);
char S1[80];
char* completo="studiare";
while(!c.vuota() && strcmp(S1,completo)!=0 ){
char S2[80];

strcpy(S1,c.fuoriCoda());
strcpy(S2,c.fuoriCoda());

char S[80];
strcpy(S,S1);

AlberoB<char*> B(S);
AlberoB<char*> C(S2);

strcat(S1,S2);
c1.inCoda(S1);

A.modRadice(S1);
A.insFiglio(SIN,B);
A.insFiglio(DES,C);

}
stampa(A);

}


void stampa(AlberoB<char*> A)
{
if(!A.nullo())
{
cout<<A.radice()<<endl;

stampa(A.figlio(SIN));
stampa(A.figlio(DES));
}

}




Ho seguito il tuo consiglio..spero adesso sia più chiaro :help:

Vincenzo1968
02-12-2008, 15:22
Ciao,

puoi mostrare il codice relativo alla classe AlberoB?

sottovento
02-12-2008, 15:25
C'e' una serie di incongruenze in questo codice, che ti porta ad avere il risultato che hai visto.

Prima di tutto, dovresti ricontrollare la struttura dati che hai deciso di utilizzare: si tratta di un albero in cui ogni nodo contiene un puntatore a char.
Va da se' che devi tutte le volte assicurarti che il puntatore sia valido (punti ad un'area di memoria valida e "tutta per se'").
In realta', e' chiaro che tutti i tuoi puntatori vanno a puntare ad una variabile locale (quindi quando uscirai da quella funzione non ci sara' piu' nulla di valido) ed oltrettutto il puntatore e' uguale per tutti i nodi, per cui conterranno tutti la stessa cosa.

Ci sono diverse strategie per correggere il codice. Siccome pero' questo ha l'aria di essere un esercizio, penso sia opportuno che ci dica quali temi della programmazione hai affrontato.

Per esempio: una cosa semplice, che ti risolverebbe i problemi, sarebbe quella di usare delle std::string all'interno nei nodi. Sempre che, ovviamente, li abbia gia' studiati e siano leciti da usare nell'esercizio.
In alternativa, puoi allocare memoria per ogni nodo che crei e copiare il valore all'interno....

alessia86
02-12-2008, 15:39
Allora la classe AlberoB.h è la seguente:

#ifndef ALBEROB_H
#define ALBEROB_H

#include <assert.h>

enum Direzione { SIN=0, DES=1 };

template <class T>
struct SNodo{
T vinfo; // parte informativa
SNodo *ppadre, *pfiglio[2]; // puntatori al padre e ai due figli
SNodo( const T& inf ): vinfo(inf)
{ ppadre = pfiglio[SIN] = pfiglio[DES] = 0;
}
~SNodo( ) {delete pfiglio[SIN]; delete pfiglio[DES];}
};

template <class T>
class AlberoB
{
protected:
SNodo<T>* pradice; // puntatore alla radice
public:

// FUNZIONI NON COSTANTI
AlberoB ();
AlberoB ( const T&);

// inserisce l'albero AC come figlio d = SIN/DES di AC
void insFiglio ( Direzione, AlberoB&);
// estrae il figlio d = SIN/DES
AlberoB<T> estraiFiglio ( Direzione);
void modRadice ( const T& );
// svuota l'albero cancellandone tutti i nodi
void svuota();
// svuota l'albero ma senza cancellare i nodi
void annulla();

// FUNZIONI COSTANTI
bool nullo() const;
// restituisce una copia dell'albero
AlberoB<T> copia ( ) const;
// mostra l'info della radice
const T& radice ( ) const;
// restituisce true se la radice è nodo foglia
bool foglia () const;
// restituisce il figlio d = SIN/DES
AlberoB<T> figlio ( Direzione d ) const;
// restituisce il padre eventualmente nullo
AlberoB<T> padre ( ) const;

};
#endif;





Mentre,la classe AlberoB.cpp è questa:

#include "AlberoB.h"

template <class T>
AlberoB<T>::AlberoB () {
pradice = 0;
}
template <class T>
AlberoB<T>::AlberoB ( const T& a) {
pradice = new SNodo<T>(a);
}

template <class T>
bool AlberoB<T>::nullo() const
{
return pradice == 0;
}

// inserisce l'albero AC come figlio d = SIN/DES di AC
template <class T>
void AlberoB<T>::insFiglio ( Direzione d, AlberoB& AC )
{
assert( !nullo() );
//assert( figlio(d).nullo() );
if ( !AC.nullo() ) {
pradice->pfiglio[d]=AC.pradice;
AC.pradice->ppadre=pradice;
}
}

// estrae il figlio d = SIN/DES
template <class T>
AlberoB<T> AlberoB<T>::estraiFiglio ( Direzione d ) {
assert( !nullo() );
AlberoB<T> A = figlio(d);
A.pradice->ppadre=0;
pradice->pfiglio[d] = 0;
return A;
}

template <class T>
void AlberoB<T>::modRadice ( const T& a ) {
assert( !nullo() );
pradice->vinfo = a;
}

// svuota l'albero cancellandone tutti i nodi
template <class T>
void AlberoB<T>::svuota() {
delete pradice; pradice = 0;
}

// svuota l'albero ma senza cancellare i nodi
template <class T>
void AlberoB<T>::annulla() {
pradice = 0;
}

// FUNZIONI COSTANTI
// restituisce una copia dell'albero
template <class T>
AlberoB<T> AlberoB<T>::copia ( ) const {
if ( nullo() ) return AlberoB<T>();
AlberoB<T> AC(radice());
AlberoB<T> fs = figlio(SIN).copia();
AlberoB<T> fd = figlio(DES).copia();
AC.insFiglio(SIN,fs);
AC.insFiglio(DES,fd);
return AC;
}

// mostra l'info della radice
template <class T>
const T& AlberoB<T>::radice ( ) const {
assert( !nullo() );
return pradice->vinfo;
}

// restituisce true se la radice è nodo foglia
template <class T>
bool AlberoB<T>::foglia () const {
return !nullo()&&figlio(SIN).nullo()&& figlio(DES).nullo();
}

// restituisce il figlio d = SIN/DES
template <class T>
AlberoB<T> AlberoB<T>::figlio ( Direzione d ) const {
assert( !nullo() );
AlberoB<T> AC;
AC.pradice = pradice->pfiglio[d];
return AC;
}

// restituisce il padre eventualmente nullo
template <class T>
AlberoB<T> AlberoB<T>::padre ( ) const {
assert( !nullo() );
AlberoB<T> AC;
AC.pradice = pradice->ppadre;
return AC;
}





:cry:

alessia86
02-12-2008, 15:46
C'e' una serie di incongruenze in questo codice, che ti porta ad avere il risultato che hai visto.

Prima di tutto, dovresti ricontrollare la struttura dati che hai deciso di utilizzare: si tratta di un albero in cui ogni nodo contiene un puntatore a char.
Va da se' che devi tutte le volte assicurarti che il puntatore sia valido (punti ad un'area di memoria valida e "tutta per se'").
In realta', e' chiaro che tutti i tuoi puntatori vanno a puntare ad una variabile locale (quindi quando uscirai da quella funzione non ci sara' piu' nulla di valido) ed oltrettutto il puntatore e' uguale per tutti i nodi, per cui conterranno tutti la stessa cosa.

Ci sono diverse strategie per correggere il codice. Siccome pero' questo ha l'aria di essere un esercizio, penso sia opportuno che ci dica quali temi della programmazione hai affrontato.

Per esempio: una cosa semplice, che ti risolverebbe i problemi, sarebbe quella di usare delle std::string all'interno nei nodi. Sempre che, ovviamente, li abbia gia' studiati e siano leciti da usare nell'esercizio.
In alternativa, puoi allocare memoria per ogni nodo che crei e copiare il valore all'interno....

qst è un esercizio..ho finito da poco di seguire il corso di algoritmi e strutture dati..Devo utilizzare la struttura ad albero utilizzando la classe AlberoB.cpp che ho appena riportato sopra..cmq non so se magari mi illustri qualche strategia.. :help:

sottovento
02-12-2008, 15:56
qst è un esercizio..ho finito da poco di seguire il corso di algoritmi e strutture dati..Devo utilizzare la struttura ad albero utilizzando la classe AlberoB.cpp che ho appena riportato sopra..cmq non so se magari mi illustri qualche strategia.. :help:

Che dovevi usare l'albero era chiaro. Quello che voglio dire e' che nell'albero ci metti un "char *".

Ad ogni ciclo crei un nodo scrivendo

AlberoB<char*> B(S);
AlberoB<char*> C(S2);

pertanto tutti i nodi che crei ad ogni ciclo punteranno TUTTI a S o S2! Quindi, quando cambi il valore di S o S2, cambi TUTTI i nodi allo stesso tempo!
Inoltre, anche B e C sono dichiarate localmente, pertanto quando questa funzione termina, non esistono piu'! Quello che vedi da quel momento in poi e' soltanto fuffa.

Purtroppo ho finito l'universita' parecchi lustri fa e non so cos'e' un corso di "Algoritmi e Strutture Dati", spero che qualcuno nel forum lo sappia.
Immagino pero' che tu conosca la memoria dinamica.... ecco: prova a riscrivere creando i nodi con new() ed assegnando loro delle stringhe create con new[], qualcosa del tipo


S = new char[LENGTH];
// Qui devi riempire S
AlberoB<char*> *B = new AlberoB<char*>(S);




Alternativamente, puoi dichiarare l'albero come di tipo
AlberoB<std::string> B;
ed assegnargli delle stringhe stl.

alessia86
02-12-2008, 16:46
Grazie sottovento..adesso ci provo subito.. :)

cionci
02-12-2008, 18:56
http://www.hwupgrade.it/forum/showthread.php?t=1649196

Inoltre non va bene il titolo generico: http://www.hwupgrade.it/forum/showthread.php?t=693363