|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
[C] Nuovo problema
Ciao a tutti! Scusate se sto tempestando il forum, ma siccome domani ho l'esame sto cercando di fare il maggior numero di esercizi possibili
![]() Allora adesso ho da fare questo.... Progettare un programma C che legge in preordine da stdin un albero generico (cioe' non necessariamente binario) etichettato con interi sui nodi e ritorna la somma dei valori delle etichette x dell'albero che soddisfano le seguenti condizioni: 1. x e' dispari; 2. il padre di x e' pari. Il programma restituisce 0 se non ci sono nodi che soddisfano le condizioni di cui sopra. L'input da dare è di questo tipo: (La prima colonna indica il numero di figli che ha il corrispondente nodo e la seconda colonna indica il nodo stesso) 3 122 1 457 0 698 0 23 2 724 1 456 0 678 2 346 0 777 0 998 Non capisco bene cosa vuol dire "il padre di x è pari". Ma x è un elemento non è un nodo ![]() Io cmq ho provato a fare un codice del genere: Codice:
#include <stdio.h> #include <malloc.h> struct nodo{ int val; struct nodo *left; struct nodo *right; }; typedef struct nodo NODO; typedef NODO *TREE; TREE ReadTree(){ TREE t=(TREE)malloc(sizeof(TREE)); int nFigli, nVal, i; scanf("%d %d", &nFigli, &nVal); t->val=nVal; t->left=NULL; t->right=NULL; for(i=0; i<nFigli; ++i){ t->left=ReadTree(); t->right=ReadTree(); } return t; } int evaluateSum(TREE t){ int sum=0; if(t==NULL) return sum; else if((t->val)%2!=0) sum+=t->val; return sum+evaluateSum(t->left)+evaluateSum(t->right); } int main(void){ TREE albero=(TREE)malloc(sizeof(NODO)); albero=ReadTree(); printf("Sum: %d", evaluateSum(albero)); return 0; } |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Ho modificato un po' il codice però la somma non mi viene esattamente come dovrebbe (dovrebbe venire 2157 invece viene 122). COsa posso fare?
Codice:
#include <stdio.h> #include <malloc.h> struct nodo{ int val; struct nodo *figlio; }; typedef struct nodo NODO; typedef NODO *TREE; TREE ReadTree(){ TREE t=(TREE)malloc(sizeof(TREE)); int nFigli, nVal, i; scanf("%d %d", &nFigli, &nVal); t->val=nVal; t->figlio=NULL; if(nFigli-- >0) t->figlio=ReadTree(); return t; } int evaluateSum(TREE t){ int sum=0; if(t==NULL) return sum; else if((t->val)%2==0){ sum+=t->val; return sum+evaluateSum(t->figlio); } else return 0; } int main(void){ TREE albero=(TREE)malloc(sizeof(NODO)); albero=ReadTree(); printf("Sum: %d", evaluateSum(albero)); return 0; } |
![]() |
![]() |
![]() |
#3 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
l'albero non deve essere binario, quindi la struct io la reimplementerei così:
Codice:
typedef struct _NODE { int nValue; struct _NODE *pChild, *pNext; } NODE, *TREE; poi la ReadTree se non erro dovrebbe diventare così: Codice:
TREE ReadTree() { TREE t = (TREE)malloc(sizeof(NODE)), **ppCur = &t->pChild; int nChildren = 0; scanf("%d %d", &nChildren, &t->nValue); t->pChild = NULL; t->pNext = NULL; while (nChildren) { *ppCur = ReadTree(); ppCur = &(*ppCur)->pNext; nChildren--; } return t; } |
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Ciao e grazie della risposta. Non capisco bene quando dici:
Quote:
Ho provato comunque il tuo codice ma non va lo stesso, cioè quando lo faccio partire si blocca. Ultima modifica di Manugal : 30-09-2005 alle 19:06. |
|
![]() |
![]() |
![]() |
#5 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
be', un albero n-ario ha n figli; come fai a rappresentarli? in ciascun nodo potresti o metterci un array, ma sarebbe difficile perché dovresti gestirlo dinamicamente, oppure, soluzione migliore, una lista (le avete fatte le liste?); io ci ho messo una lista: il puntatore pChild punta alla testa della lista e pNext punta all'elemento successivo. per esempio:
Codice:
1 | 2-----3-----4 | | 5--6 7--8 | 9 ogni sbarretta verticale corrisponde concettualmente a un puntatore pChild, mentre le sbarrette orizzontali corrispondono a pNext. |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Si si le liste le abbiamo fatte, solamente non riesco a spiegarmi perché usare un puntatore a puntatore. Cioè pChild è già un puntatore di suo (un puntatore a struttura), quindi se io devo rappresentare ad esempio 3 filgi su un nodo, non potrei usare p->pChild normalmente dicendogli che finché il numero di figli è maggiore di zero deve richiamare ricorsivamente ReadTree() su p->pChild? E poi i fratelli come li gestisco? Al solito con la ricorsione?
|
![]() |
![]() |
![]() |
#7 | ||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
Quote:
![]() per effettuare la ricorsione su un albero N-ario devi fare più o meno così: Codice:
void Ricorsione(TREE t) { if (!t) { return; } DoSomething(t->nValue); Ricorsione(t->pChild); Ricorsione(t->pNext); } ![]() |
||
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Ok ho capito. Allora questa istruzione all'interno del while a cosa serve?
Codice:
ppCur = &(*ppCur)->pNext; ![]() ![]() |
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Apr 2004
Messaggi: 130
|
Codice:
typedef struct nodo { int dato; struct nodo** next; } Nodo; Nodo *readTree(FILE *f) { int valore, figli; Nodo *n = malloc(sizeof(Nodo)); fscanf(f, "%d %d", &figli, &valore); n->dato = valore; if (figli > 0) { int i; n->next = malloc((figli+1) * sizeof(Nodo *)); for (i = 0; i < figli; ++i){ n->next[i] = readTree(f); } n->next[i] = NULL; } else n->next = NULL; return n; } int valutaSomma(Nodo *n) { int risultato = 0; if (n == NULL) return 0; if (n->dato % 2 != 0) risultato = n->dato; else if (n->next != NULL) { Nodo **p; for (p = n->next; *p; ++p) risultato += valutaSomma(*p); } return risultato; } Ultima modifica di Qu@ker : 01-10-2005 alle 08:56. |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Come mai hai usato un array di puntatori? E i figli come fai a gestirli se hai solamente next nella struct (anzi più che i figli i fratelli)? Potresti commentarmi il codice? Grazie.
![]() Ultima modifica di Manugal : 01-10-2005 alle 10:58. |
![]() |
![]() |
![]() |
#11 |
Member
Iscritto dal: Apr 2004
Messaggi: 130
|
I 'fratelli' (o meglio, i loro puntatori) stanno tutti nello stesso array.
Il codice? Mah ...e' autoesplicativo! ![]() Ultima modifica di Qu@ker : 01-10-2005 alle 11:54. |
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
In effetti si riguardandolo bene.
![]() Ma come mai quando hai fatto if(Figli>0), hai allocato un nuovo nodo con figli+1? Poi il testo dice anche di controllare che x sia dispari e che il padre di x sia pari. Ma non riesco a capire cosa intende dire... cioè x è un elemento da come si può dedurre dal testo, non un nodo. Ultima modifica di Manugal : 01-10-2005 alle 12:19. |
![]() |
![]() |
![]() |
#13 |
Member
Iscritto dal: Apr 2004
Messaggi: 130
|
Perche' utilizzo un elemento dell'array per segnalare che non ci sono piu' figli, inserendoci NULL (alle volte questo elemento viene definito 'sentinella').
L'alternativa era di inserire nella struct un campo contenente il numero dei figli. |
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Ok grazie credo di aver capito
![]() |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Scusa ancora.... sto provando il tuo programma però quando lo faccio partire non stampa niente (uso Dev-C++ e quando c'è qualche problema non mi da nessun messaggio quindi non so dirti da cosa dipenda). Ti posto il main:
Codice:
int main(void){ Nodo *t=malloc(sizeof(Nodo)); FILE *ifp; ifp=fopen("input3.txt", "r"); t=readTree(ifp); valutaSomma(t); fclose(ifp); return 0; } |
![]() |
![]() |
![]() |
#16 |
Member
Iscritto dal: Apr 2004
Messaggi: 130
|
Codice:
int main(void) { Nodo *radice; FILE *in = fopen("dati.txt", "r"); if (in == NULL) { perror("fopen()"); exit(1); } radice = readTree(in); fclose(in); printf("Il risultato e\': %d\n", valutaSomma(radice)); return 0; } |
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
|
Hai ragione ho scordato la printf
![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:25.