Strutture dati: Array


DEFINIZIONE

Con il termine array si intende un tipo di struttura dati complessa che trae le proprie caratteristiche dalla definizione matematica di vettore.

Un array può essere visto come una serie di celle contigue ognuna delle quali ha il compito di contenere un determinato dato. Ogni cella che compone tale struttura è accessibile mediante una chiave denominata indice. L’’indice è un fattore fondamentale per accedere ai dati interni al vettore e nella maggior parte dei linguaggi di programmazione è di tipo numerico intero. I valori di tali parametro sono spesso contigui e possono partire da 0 o da 1.

Ad esempio, se volessi accedere al primo elemento di un array di nome vettore, il cui primo indice è 0 mi basterà usare la sintassi:

vettore[0]

mentre per accedere al terzo elemento dovrò utilizzare l’’indice 2:

vettore[2]

Bisogna precisare che nei linguaggi compilati, l’’uso degli indici di questa struttura, porta a degli errori se non si trattano in maniera consona questi parametri poiché tali linguaggi non hanno alcun riferimento in memoria della dimensione dei vettori con cui si lavora. Questo è un punto fondamentale poiché, l’’uso scorretto degli indici, può portare ad ottenere di dati errati e quindi potenzialmente pericolosi.

DATI DEGLI ARRAY

La concezione dei tipi di dati degli array varia in base ai diversi linguaggi di programmazione. Nel C, ad esempio, quando si definisce un vettore esso viene inizializzato con un tipo di dato che dovrà essere poi compatibile con i singoli dati in esso contenuti. Questo vuol dire che se all’’atto della definizione di un array lo dichiaro di tipo int, esso potrà contenere solo dati di tipo int. Nel PHP, invece, non importa il tipo di dato che l’’array andrà a contenere poiché il linguaggio è di tipo typeless.
Il prototipo di dichiarazione del lingaggio C è:

tipo nome_array[numero elementi];

pertanto un esempio di definizione può essere:

float vector[5];

Si nota come si sia definito un vettore di 6 elementi tutti di tipo float al quale è possibile accedere subito dopo la sua creazione. Se volessimo, infatti, inizializzare i suoi dati con i primi 6 numeri reali basterà utilizzare la sintassi

nome_array[indice] = dato;

Che nel nostro caso sarà:

vector[0] = 0.0;
vector[1] = 1.0;
vector[2] = 2.0;
vector[3] = 3.0;
vector[4] = 4.0;
vector[5] = 5.0;

DINAMICITÀ

Un array, nella maggior parte dei casi, può subire modifiche durante l’’uso del programma. Basti immaginare, ad esempio, un vettore che deve contenere le macchine parcheggiate in un parcheggio custodito. Ogni indice dell’’array indica un posto numerato e il dato in esso contenuto sarà il modello della macchina. Se un giorno il padrone del parcheggio decide di ampliare lo stabile aggiungendo nuovi posti allora anche l’’array dovrà essere ampliato per contenere nuovi indici. In tal caso basterà ricorrere ai mezzi che ogni linguaggio di programmazione pone a disposizione dello sviluppatore per riallocare la memoria utile a tale fine. Questo evidenzia come, se adeguatamente trattata, l’’array è una struttura dati dinamica. Tale concetto di dinamicità (array allocato dinamicamente) è da separare dal concetto di array dinamico.
Un array si definisce dimanico quando consente di aggiungere e/o rimuovere alcuni elementi. Esso si compone di due zone separate: la prima viene allocata e definita come un comune array mentre la seconda è nascosta ed è dedicata ai futuri allocamenti. Tale sezione può essere utilizzata sino a che la sua memoria non si esaurisce. L’’uso degli array dinamici risulta alle volte troppo dipspendioso sia in termini di spazio che di tempo poiché, una sua riscrittura, può richiedere anche la copia dell’’intero array.

ARRAY MULTIDIMENSIONALI

Sino ad ora abbiamo trattato vettori i cui dati erano accessibili mediante un solo indice. Può accadere, per esigenze di sviluppo, che si abbia bisogno di più indici da trattare. Tali elementi vengono chiamati array multidimensionali. Immaginiamo di voler utilizzare un array che mi indichi se in un determinato punto cartesiano ci sia o no un punto mediante la presenza di un 1 o un 0. I dati di tale vettore potranno essere accessibili mediante l’’uso di due indici: uno che indichi il valore dell’’asse delle ascisse da considerare ed uno quello delle ordinate.

Se, ad esempio, in un piano cartesiano prendiamo in considerazione le coppie di valori (2, 2), (2, 3), (3, 2) e (3, 3) e sappiamo che sono presenti solo due punti nelle coordinate (2, 2) e (3, 3), il nostro array potrà essere consultato accedendo ai dati mediante la sintassi:

nome_array[indice 1][indice 2]

Nel nostro caso sarà:

vettore[2][2] = 1;
vettore[2][3] = 0;
vettore[3][2] = 0;
vettore[3][3] = 1;

E’ facile notare come tale discorso può essere facilmente espanso ad array con un numero maggiore di indici.

CONCLUSIONI

L’array è sicuramente una delle strutture dati più semplice da gestire e da utilizzare. La sua convenienza, in termini tecnici, è da apprezzare per un suo uso basilare. Quando i dati iniziano a diventare eccessivamente numerosi e quando le dimensioni iniziano a crescere e sicuramente molto più pratico puntare ad altre strutture più consone a questi compiti.

Strutture dati: Generalità

Inauguriamo una nuova sezione del blog che avrei voluto iniziare già diverso tempo addietro ma che, per mancanza di tempo, non ho mai cominciato a scrivere.
La nuova sezione, particolarmente interessante per chi vuole approfondire la programmazione ad un livello più alto, tratterà le strutture dati. Per studiare gli algoritmi che gestiscono questi tipi di elementi, useremo il C/C++ vista la potenza del linguaggio e data la presenza dei puntatori che favoriscono la possibilità di sfruttare le qualità stesse delle strutture.

STRUTTURE DATI

Le strutture dati sono dei particolari strumenti strutturali mediante i quali è possibile organizzare un insieme di dati e mantenerli o in memoria centrale, per tutta la durata dell’uso del software, o per riversarli nella memoria di massa per eventuali modifiche successive.

Un buon uso delle strutture dati, prevede la possibilità di utilizzare dati di tipo diverso nello stesso elemento strutturale. Proprio per tale motivo, quando si scrive un algoritmo che gestisce una struttura, la si deve vedere come una situazione il più possibile generica senza soffermarsi in maniera particolare sul tipo di dato da utilizzare. In questo modo si scriverà codice perfettamente utilizzabile in ogni situazione in cui l’utente può trovarsi.

ALGORITMI

Come si è accennato, le strutture dati sono gestite da particolari algoritmi studiati appositamente per la struttura presa di volta in volta in esame.
Un’algoritmo è una serie di step (passi) da effettuare per poter giungere alla realizzazione di uno scopo prefissato. La serie di passi effettuati deve essere finita e deve giungere sempre alla risoluzione del problema iniziale. Un algoritmo deve godere dell’ottimizzazione per la richiesta di memoria al sistema e/o per la richiesta di cicli e quindi di tempo di esecuzione. Tuttavia un buon algoritmo si basa anche su altri parametri quali robustezza, stabilità, modularità, etc…

Una buona organizzazione della struttura dati, favorisce la stesura di buoni algoritmi sia in termini di uso di memoria che di velocità. Ad esempio, cercare una parola all’interno di una lista risulterà più facile se quest’ultima è ordinata e, in tale situazione, l’algoritmo sarà scritto in maniera tale da cercare la parola in base a come è ordinata la lista.
Anche la scelta di una struttura, anziché un’altra, in base alla situazione, porta all’ottimizzazione del codice che la gestirà.

COME SCEGLIERE LA STRUTTURA

La scelta della struttura dati più adatta deve essere studiata dal programmatore e richiede la considerazione di diversi fattori
  • Risorse necessarie (codice più veloce o più leggero?)
  • Inserimento degli elementi (In testa, in coda o in ordine casuale?)
  • Prelievo degli elementi (In testa, in coda o in ordine casuale?)
  • Eliminazione degli elementi (In testa, in coda o in ordine casuale?)
Bisogna tener presente che l’uso di una particolare struttura dati può favorire alcuni fattori ma può essere poco pratica per altri. Questo vuol dire che non esiste la struttura perfetta ma quella più adatta ad ogni situazione. Questo vuol dire che c’è, ad esempio, quella più adatta all’ordinamento, quella migliore per il prelievo o quella migliore per l’inserimento.

STRUTTURE DATI DINAMICHE

Le strutture dati possono essere catalogate in base alle loro prestazioni nelle diverse situazioni o in base alle operazioni che è possibile effettuare sulle stesse. Con il termine strutture dati dinamiche si intendono quelle particolari strutture che fanno uso dei puntatori e della locazione dinamica della memoria per la gestione dei propri elementi in fase di esecuzione. Ogni elemento è in qualche modo connesso almeno ad un altro e tale connessione può essere cambiata durante lo svolgimento del software. Qualora l’uso dei puntatori non fosse possibile si può ricorrere ad altri sistemi che però peccano per carenza di flessibilità.

Tra esse troviamo, ad esempio, liste, alberi, grafi e tabelle. Ognuna di esse sarà analizzata in futuro in maniera approfondita.

CONTENITORI

I contenitori sono strutture derivate da quelle dinamiche e si concentrano in maniera particolare sulla gestione dell’inserimento e del prelievo dei dati presenti all’interno. L’accesso ai dati di queste strutture è l’elemento che differisce tra ognuna di esse. C’è chi preleva i dati in testa, chi in coda e chi in base ad un indice.

Tra esse troviamo, ad esempio, la pila o la coda. Ognuna di esse sarà analizzata in futuro in maniera approfondita.

Abbiamo eseguito una breve carrellata di ciò che si studierà in questa sezione.

Alla prossima!!!