Innanzitutto le funzioni ListaVuota() sono superflue.
-------------------------------------------------------------------------
int i = 0;
while(i < RIG)
{
a = AggiungiRigaInCoda(a, Vett[i], COL);
i++;
}
Hai qualcosa contro il for?
-------------------------------------------------------------------------
Passiamo alla funzione StampaMatrice()... utilizzando i for al posto dei while e rimuovendo la variabile temp che è superflua, si ottiene:
void StampaMatrice(RNodo *p)
{
for(unsigned int i = 0; i < RIG; ++i)
{
for(unsigned int j = 0; j < COL; ++j)
{
printf("%d ", p->dato->el);
p->dato = p->dato->prox;
}
printf("\n");
p = p->prox;
}
}
Innanzitutto è concettualmente sbagliato, oltre che inutile, utilizzare delle dimensioni (mi riferisco a RIG e COL) quando si ha a che fare con delle liste, basta sfruttare il fatto che l'ultimo elemento punta a NULL. Quindi il codice diventa:
void StampaMatrice(RNodo *p)
{
for(; p; p = p->prox)
{
for(; p->dato; p->dato = p->dato->prox)
{
printf("%d ", p->dato->el);
}
printf("\n");
}
}
A questo punto ti faccio notare che stai andando a modificare i membri dato di p, i quali all'uscita della funzione punteranno tutti a NULL. Per il secondo for quindi diventa indispensabile utilizzare una variabile temporanea:
void StampaMatrice(RNodo *p)
{
for(; p; p = p->prox)
{
for(CNodo *temp = p->dato; temp; temp = temp->prox)
{
printf("%d ",temp->el);
}
printf("\n");
}
}
Come alternativa potresti anche utilizzare le funzioni stampa_1() e stampa_2() che ho postato in precedenza.
-------------------------------------------------------------------------
Per quanto riguarda l'aggiunta in coda classica (ossia la funzione AggiungiInCoda()) mi sembra corretta, ma un po' ridondante. Potresti per esempio ricorrere a qualcosa del genere
nodo* aggiungi_in_coda(nodo *p, int n)
{
nodo *nuovo = (nodo*)malloc(sizeof(nodo));
nuovo->data = n;
nuovo->next = NULL;
if(!p)
{
p = nuovo;
}
else
{
nodo *temp = p;
while(temp->next)
{
temp = temp->next;
}
temp->next = nuovo;
}
return p;
}
o ancora meglio utilizzare i puntatori doppi implementando la funzione di aggiunta in coda sfruttando quella di aggiunta in testa
void aggiungi_in_testa(nodo **p, int n)
{
nodo *nuovo = (nodo*)malloc(sizeof(nodo));
nuovo->data = n;
nuovo->next = *p;
*p = nuovo;
}
void aggiungi_in_coda(nodo **p, int n)
{
while(*p)
{
p = &(*p)->next);
}
aggiungi_in_testa(p, n);
}
-------------------------------------------------------------------------
Lo stesso identico discorso vale anche per CreaNodoRiga().
-------------------------------------------------------------------------
Infine analizziamo la funzione AggiungiRigaInCoda(). Il problema qui è che CreaNodoRiga() restituisce sempre la testa della lista, quindi tutti gli array passati alla funzione saranno copiati sempre nel primo elemento della lista più esterna. Per intenderci, all'uscita del ciclo while nel main(), la lista di liste a sarà costituita da qualcosa del genere:
Soluzione? Ce ne sono molte, ma credo che la cosa più semplice sia unire CreaNodoRiga() e AggiungiRigaInCoda() in un'unica funzione del tipo:
nodo_2* aggiungi_in_coda_2(nodo_2 *p, int *v, unsigned int dim)
{
nodo_2 *nuovo = (nodo_2*)malloc(sizeof(nodo_2));
nuovo->data = NULL;
for(unsigned int i = 0; i < dim; ++i)
{
nuovo->data = aggiungi_in_coda_1(nuovo->data, v[i]);
}
nuovo->next = NULL;
if(!p)
{
p = nuovo;
}
else
{
nodo_2 *temp = p;
while(temp->next)
{
temp = temp->next;
}
temp->next = nuovo;
}
return p;
}