Il testo dell'esercizio è questo:
Il programma richiede di eseguire un pattern matching dove il pattern è costituito dai campi info dei nodi di
un albero binario ordinati secondo il percorso in larghezza, mentre il pattern è semplicemente un array di
dimP interi.
Il problema va risolto in 2 passi:
1) Va definita una funzione iterativa nodoE* faiIter(nodo*r) che restituisce la lista L dei nodi estesi
nodoE che puntano ai nodi di albero(r) percorsi in larghezza.
La struttura nodoE è come segue:
struct nodoE{nodo* info; nodoE* next; nodoE(nodo*a=0, nodoE*b=0){info=a; next=b;}};
nodo è invece il solito nodo degli alberi binary.
2) Va definita una funzione ricorsiva int matchRic(nodoE*L, int*P, int dimP) che riceve la lista L
prodotta nel passo 1, il pattern P e la lunghezza del pattern dimP e restituisce la massima lunghezza
di match di P che si trova nei nodi puntati da L. Infatti il match da considerare può essere anche
incompleto ed è spiegato nell’esempio che segue.
Esempio 1: . Si consideri il seguente albero binario r:
10(5(10(1(_,_),2(_,_)),2(3(_,_),1(_,_))),5(_,1(3(_,_),2(_,_)))) esso contiene 12 nodi.
Allora la lista L che faiIter deve produrre contiene 12 nodi di tipo nodoE. Il primo di essi punta alla
radice r (che ha info=10), il secondo al figlio sinistro (info=5) di r, il terzo al figlio destro (info=5) di
r, il quarto al figlio sinistro del figlio sinistro di r (info=10) e così via. Quindi la sequenza dei campi
info puntati dai nodoE di L sarà: 10,5,5,10,2,1,1,2,3,1,3,e 2. Nel seguito chiamiamo questa sequenza
semplicemente L. Assumiamo ora che P=[2,5,10,2]. Se partiamo dal primo valore di L (10), esso
matcha la terza posizione di P, dopo di che il prossimo valore di L (5) non matcha l’ultimo elemento
di P che è 2. Per cui il match a partire dalla prima posizione di L ha lunghezza 1. Consideriamo ora il
match che parte dalla seconda posizione di L: 5 matcha la seconda posizione di P, poi il successivo 5
non matcha nessun successivo elemento di P. Quindi anche questo match ha lunghezza 1. Partiamo
ora dal terzo elemento di L che è 5, esso matcha il secondo elemento di P, il successivo 10 di L
matcha il terzo elemento di P, e il successivo elemento di L (2) matcha l’ultimo elemento di P.
Quindi abbiamo trovato un match di lunghezza 3. Non è difficile vedere che i successivi tentativi
troveranno match più corti di 3 e quindi la risposta che matchRic dovrebbe dare è 3.
Nota: eventuali funzioni ausiliarie di faiRic devono essere ricorsive e di matchIter devono essere
iterative
La prima parte l'ho fatta utilizzando una struttura FIFO che ha come campi i puntatori nodoE* rispettivamente primo e ultimo. Compilando la prima parte mi risulta corretta invece per quanto riguarda la seconda parte, ci sono degli errori. Ho particolarmente urgenza in quanto domani ho l'appello d'esame quindi se qualcuno mi riesce a spiegare nel dettaglio cosa ho sbagliato mi farebbe un enorme favore. Grazie in anticipo. Vi riporto successivamente il codice che ho scritto:
#include<iostream>
using namespace std;
struct nodo { int info; nodo* left, * right; nodo(int a = 0, nodo* b = 0, nodo* c = 0) { info = a; left = b; right = c; } };
struct nodoE { nodo* info; nodoE* next; nodoE(nodo* a = 0, nodoE* b = 0) { info = a; next = b; } };
struct FIFO {
nodoE* primo;
nodoE* ultimo;
FIFO(nodo* a = 0) {
if (a) primo = ultimo = new nodoE(a);
else
primo = ultimo = 0;
}
};
nodo* pop(FIFO& x) {
nodoE* a = x.primo;
x.primo = x.primo->next;
if (!x.primo)
x.ultimo = 0;
return a->info;
}
FIFO push(nodo* x, FIFO y) {
if (y.primo) {
y.ultimo->next = new nodoE(x);
y.ultimo = y.ultimo->next;
return y;
}
return FIFO(x);
}
nodoE* faiIter(nodo* r) {
FIFO coda(r);
while (coda.primo) {
nodo* x = pop(coda);
cout << x->info << " ";
if (x->left) coda = push(x->left, coda);
if (x->right) coda = push(x->right, coda);
}
return coda.primo;
}
void stampaLista(nodoE* lista) {
if (lista) {
cout << lista->info->info << " ";
stampaLista(lista->next);
}
}
bool check(nodoE* lista, int* A, int dimA) {
if (dimA) {
if (lista->info->info == *A) return true;
else {
return check(lista->next, A + 1, dimA - 1);
}
}
else
return false;
}
int scorri(nodoE* L, int* A, int dimA,int h) {
if (!dimA) return h;
if (L && dimA) {
if (L->info->info == *A) {
if (L->next) return scorri(L->next, A + 1, dimA - 1, h++);
else {
return ++h;
}
}
else return scorri(L, A + 1, dimA - 1, h);
}
if(!L) return h;
}
int matchRic(nodoE* L, int* P, int dimP,int & max) {
if (!dimP) return 0;
if (L) {
if (check(L, P, dimP) == true) {
int max2 = scorri(L, P, dimP, 0);
if (max2 > max) max = max2;
}
else
return matchRic(L->next, P, dimP,max);
}
return max;
}
int main() {
nodo* albero = new nodo(5, new nodo(10), new nodo(4));
albero->left->left = new nodo(7);
albero->left->right = new nodo(2);
albero->right->right = new nodo(5);
nodoE* x = faiIter(albero);
stampaLista(x);
int max = 0;
int A[]{ 2,5,10 }; int dimA = 3;
cout << matchRic(x, A, dimA, max);
}