Array di Array in C#
Gli array di array, chiamati anche in inglese Jagged Array o Array Irregolari, rappresentano un approccio flessibile per gestire strutture di dati annidate, poiché ogni riga può contenere un numero variabile di elementi.
In C#, si costruiscono come array di array, consentendo un controllo dettagliato della memoria e dell’organizzazione dei dati. In questo articolo scopriremo come dichiararli, allocarli e utilizzarli. Inoltre, esamineremo un esempio pratico di come costruire il Triangolo di Tartaglia utilizzando un array di array.
Array di Array
In C# possiamo avere array di array, che chiamiamo jagged arrays.
I jagged arrays sono array di array, ovvero array in cui ogni riga contiene a sua volta un proprio array, e quest'ultimo può avere una lunghezza diversa rispetto alle altre righe. Questo è diverso dagli array multidimensionali, in cui tutte le righe hanno la stessa lunghezza.
Array di Array (Jagged Arrays)
Un Jagged Array è un array in cui ogni elemento è un array. Ogni array può avere una lunghezza diversa.
Dichiarazione e Allocazione di un Array di Array
L'unica differenza nella dichiarazione dei jagged array rispetto agli array multidimensionali regolari è che non abbiamo una sola coppia di parentesi quadre.
Con i jagged array, abbiamo una coppia di parentesi quadre per dimensione.
Li allochiamo in questo modo:
int[][] jaggedArray;
jaggedArray = new int[2][];
jaggedArray[0] = new int[5];
jaggedArray[1] = new int[3];
Ecco come dichiariamo, allocchiamo e inizializziamo un array di array (un jagged array i cui elementi sono array di valori interi):
int[][] myJaggedArray = {
new int[] {5, 7, 2},
new int[] {10, 20, 40},
new int[] {3, 25}
};
Da notare che ogni riga è un array che va allocato separatamente. In questo caso, myJaggedArray
è un array di tre array di interi. Ogni array interno ha una lunghezza diversa.
Dichiarazione di un Jagged Array
Per dichiarare un jagged array, usiamo la seguente sintassi:
tipo[][] nomeArray;
Allocazione in Memoria
La figura sottostante illustra come il jagged array myJaggedArray
dichiarato nell'esempio di sopra sia allocato in memoria:
Come possiamo vedere, i jagged array sono un insieme di riferimenti. Un jagged array non contiene direttamente altri array, ma ha elementi che puntano ad essi.
La dimensione non è nota e per questo il sistema di runtime .NET (il CLR) mantiene solo riferimenti agli array interni. Dopo aver allocato la memoria per un elemento di array, quel riferimento inizia a puntare al nuovo blocco creato nella memoria dinamica.
La variabile myJaggedArray
è memorizzata nello stack di esecuzione del programma e punta a un blocco nella memoria dinamica, che contiene una sequenza di tre riferimenti ad altri tre blocchi in memoria; ognuno di essi contiene un array di numeri interi, ossia gli elementi del jagged array.
Inizializzazione e Accesso agli Elementi
Possiamo accedere agli elementi degli array che fanno parte dell'array jagged utilizzando il loro indice.
Nel prossimo esempio accederemo all'elemento con indice 3 dell'array memorizzato all'indice 0 in myJaggedArray
dichiarato sopra:
myJaggedArray[0][2] = 45;
Gli elementi dell'array jagged possono essere array monodimensionali oppure array multidimensionali. Ecco un esempio di jagged array di array bidimensionali:
int[,][] jaggedOfMulti = new int[2][,];
jaggedOfMulti[0] = new int[,] {
{ 5, 15 },
{ 125, 206 }
};
jaggedOfMulti[1] = new int[,] {
{ 3, 4, 5 },
{ 7, 8, 9 }
};
Esempio: Costruzione del Triangolo di Tartaglia
Nel prossimo esempio useremo un jagged array per generare e visualizzare il Triangolo di Tartaglia.
Come sappiamo dalla matematica, la prima riga del triangolo contiene il numero 1 e ogni numero successivo è generato dalla somma dei due numeri nella riga sopra.
Il triangolo di Tartaglia ha l'aspetto che segue:
Per avere un Triangolo di Tartaglia di un'altezza data (ad esempio 12), allochiamo un jagged array triangle[][]
, che contiene 1 elemento nella riga zero, 2 nella prima, 3 nella seconda, ecc.
Per prima cosa, inizializziamo triangle[0][0] = 1
, mentre il resto delle celle avrà valore predefinito 0 grazie all'allocazione.
Poi iteriamo sulle righe e dalla riga row
calcoliamo i valori per la riga row + 1
. Per farlo usiamo due cicli for
annidati che scorrono le colonne nella riga corrente e nella successiva, e applichiamo le definizioni del Triangolo di Tartaglia per i valori del triangolo: aggiungiamo il valore della cella corrente della riga attuale (triangle[row][col]
) alla cella a sinistra nella riga successiva (triangle[row + 1][col]
) e alla cella in basso a destra (triangle[row + 1][col + 1]
).
Stampiamo usando un numero appropriato di spazi (usando il metodo PadLeft()
della classe String
), perché vogliamo che il risultato sia allineato.
Ecco il codice dell'algoritmo descritto:
class TartagliaTriangle
{
static void Main()
{
// Altezza del Triangolo di Tartaglia
const int HEIGHT = 12;
// Allochiamo l'array in forma di triangolo
long[][] triangle = new long[HEIGHT + 1][];
for (int row = 0; row < HEIGHT; row++)
{
triangle[row] = new long[row + 1];
}
// Calcolo del Triangolo di Tartaglia
triangle[0][0] = 1;
for (int row = 0; row < HEIGHT - 1; row++)
{
for (int col = 0; col <= row; col++)
{
triangle[row + 1][col] += triangle[row][col];
triangle[row + 1][col + 1] += triangle[row][col];
}
}
// Stampa del Triangolo di Tartaglia
for (int row = 0; row < HEIGHT; row++)
{
Console.Write("".PadLeft((HEIGHT - row) * 2));
for (int col = 0; col <= row; col++)
{
Console.Write("{0,3} ", triangle[row][col]);
}
Console.WriteLine();
}
}
}
Se eseguiamo il programma, vedremo che funziona correttamente e genera il Triangolo di Tartaglia per un certo numero di righe (nel nostro caso HEIGHT = 12
):
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
In Sintesi
In questa lezione abbiamo appreso che:
- I jagged arrays sono array di array, dove ogni elemento punta a un array distinto.
- Si allocano specificando la dimensione del contenitore esterno e poi, per ogni indice, definendo la lunghezza dell’array interno.
- A differenza di un array multi-dimensionale classico, ogni riga può avere dimensioni differenti.
- L’esempio del Triangolo di Tartaglia illustra come sfruttare questo modello per generare una struttura con larghezza variabile in ogni riga.
- La gestione degli indici e delle inizializzazioni richiede attenzione, ma offre grande libertà nella gestione dei dati.