La scelta della giusta struttura dati può rendere il tuo programma più efficiente. Ecco una guida per aiutarti a fare la scelta giusta.

La scelta della migliore struttura di dati per i tuoi obiettivi potrebbe essere difficile con più opzioni disponibili. Quando scegli una struttura dati, considera i dati con cui avrai a che fare, le operazioni da eseguire sui dati e l'ambiente in cui verrà eseguita la tua applicazione.

Comprendi i tuoi dati

Comprendere i dati con cui ti occuperai prima di selezionare una struttura dati è fondamentale. Strutture dati comuni che funzionano con vari tipi di dati includono matrici, elenchi collegati, alberi, grafici e tabelle hash.

Ad esempio, quando devi accedere agli elementi in modo casuale dai tuoi dati, gli array potrebbero essere la scelta migliore. Nel caso in cui tu abbia costantemente bisogno di aggiungere o eliminare elementi da un elenco e anche la dimensione dell'elenco potrebbe cambiare, allora gli elenchi collegati possono essere particolarmente utili.

instagram viewer

Quando è necessario archiviare in modo efficace più livelli di dati, come le strutture dei record, ed eseguire operazioni come la ricerca e l'ordinamento, gli alberi sono utili.

Quando è necessario descrivere le interazioni tra entità, come quelle nei social network, ed eseguire operazioni come il percorso più breve e la connettività, sono preferiti i grafici. Le tabelle hash sono utili per veloci ricerche chiave.

Considera le operazioni da eseguire sui dati

Nella scelta di una struttura dati, bisogna considerare anche le operazioni da eseguire sui dati. Diverse strutture di dati ottimizzano numerose azioni, come l'ordinamento, la ricerca, l'inserimento e l'eliminazione.

Ad esempio, gli elenchi collegati sono migliori per azioni come l'inserimento e l'eliminazione, ma gli alberi binari sono i migliori per la ricerca e l'ordinamento. Una tabella hash può essere la scelta migliore se l'applicazione richiede l'inserimento e la ricerca simultanei.

Valutare l'ambiente

Quando si considera una struttura dati, è necessario valutare l'ambiente in cui verrà eseguita l'applicazione. L'ambiente influenza la qualità e la rapidità con cui sono accessibili le strutture dati.

Considera i seguenti fattori quando valuti la tua condizione attuale:

  1. Potenza di calcolo: scegli strutture di dati per le tue applicazioni che funzionino bene su PC con poca potenza di elaborazione durante l'esecuzione sulla piattaforma. Ad esempio, strutture di dati più semplici come gli array potrebbero essere più appropriate di alberi o grafici.
  2. Concorrenza: dovresti scegliere una struttura dati thread-safe in grado di gestire l'accesso simultaneo senza danneggiamento dei dati; se l'applicazione viene eseguita in un ambiente concorrente, in cui più thread o processi accedono contemporaneamente alla struttura dei dati. In questo caso, strutture dati senza blocco come ConcurrentLinkedQueue E ConcurrentHashMap potrebbe essere più appropriato di quelli tradizionali come ArrayListing e HashMap.
  3. Latenza di rete: se la tua applicazione richiede il trasferimento dei dati su una rete, devi considerare la latenza della rete mentre decidi la migliore struttura dei dati. In tali situazioni, l'utilizzo di una struttura dati che limita le chiamate di rete o riduce la quantità di trasferimento dati può aiutare a migliorare l'esecuzione.

Strutture di dati comuni e relativi casi d'uso

Di seguito è riportato un riepilogo di diverse strutture di dati popolari e del loro utilizzo.

  1. Array: Questa è una struttura dati semplice ed efficiente che può contenere una serie di elementi di dimensioni fisse dello stesso tipo di dati. Affinché funzionino correttamente, hanno bisogno di un accesso rapido e diretto a oggetti specifici tramite un indice.
  2. Liste collegate: le liste concatenate sono costituite da nodi, che contengono un elemento e un riferimento al nodo successivo e/o al nodo precedente. A causa delle loro operazioni efficienti, gli elenchi collegati sono più adatti in situazioni che richiedono l'inserimento o l'eliminazione frequente di elementi. Tuttavia, l'accesso ai singoli elementi tramite indice negli elenchi collegati è più lento rispetto agli array.
  3. Code e pile: le pile aderiscono alla regola LIFO (Last-In-First-Out), in cui l'ultimo elemento inserito è il primo elemento rimosso. Le code sono regolate dal principio FIFO (First-In-First-Out). dove il primo elemento aggiunto è anche il primo eliminato.
  4. Tabelle hash: le tabelle hash sono una forma di struttura dati che contiene coppie chiave-valore. La soluzione migliore consiste nell'utilizzare le tabelle hash quando il numero di componenti è imprevedibile ed è necessario un rapido accesso ai valori tramite chiave.
  5. Alberi: Gli alberi sono strutture di dati gerarchiche che possono memorizzare un gruppo di elementi in una gerarchia. I migliori usi per alberi binari di ricerca sono in strutture di dati gerarchiche in cui le relazioni tra gli elementi di dati possono rappresentare una struttura ad albero.

Scelta della giusta struttura dati

Prima di scegliere una struttura dati, considera i dati, gli obblighi e l'ambiente della tua applicazione. Mentre procedi con la tua scelta, pensa ai seguenti elementi:

  1. Complessità temporale: le prestazioni dell'applicazione potrebbero essere notevolmente influenzate dalla complessità temporale della struttura dei dati. Se la tua applicazione richiede frequenti operazioni di ricerca o recupero, utilizza una struttura dati con una complessità temporale ridotta, come una tabella hash.
  2. Complessità spaziale: La complessità dello spazio della struttura dei dati è un'altra considerazione importante. Se la tua applicazione utilizza molta memoria, scegli una struttura di dati con minore complessità di spazio, ad esempio un array. Se lo spazio non è un problema, puoi utilizzare una struttura dati con una maggiore complessità spaziale, come un albero.
  3. Leggi vs. Scrivere operazioni: se la tua applicazione utilizza molte operazioni di scrittura, scegli una struttura dati con prestazioni di inserimento più rapide, come una tabella hash. Se la tua applicazione richiede molte operazioni di lettura, scegli una struttura dati con una velocità di ricerca più rapida, ad esempio un albero di ricerca binario.
  4. Tipo di dati: i dati con cui hai a che fare potrebbero anche influire sulla struttura dei dati scelta. Ad esempio, puoi utilizzare una struttura di dati ad albero se i tuoi dati sono gerarchici. Se disponi di dati semplici a cui è necessario accedere in modo casuale, la scelta di una struttura di dati basata su array può essere l'opzione migliore.
  5. Librerie disponibili: Considera le librerie che sono facilmente accessibili per la struttura dati che stai considerando. Potrebbe essere più facile da eseguire e mantenere se il tuo linguaggio di programmazione dispone di librerie integrate disponibili per una determinata struttura di dati.

Il seguente esempio di Python dimostra come selezionare la migliore struttura di dati per un particolare caso d'uso.

Considera il caso in cui stai sviluppando un'applicazione file system che deve archiviare e recuperare file in una gerarchia. È necessario scegliere una struttura dati in grado di rappresentare in modo efficiente questa struttura gerarchica ed eseguire rapidamente operazioni come la ricerca, l'inserimento e l'eliminazione.

Potrebbe essere una buona idea utilizzare una struttura dati basata su albero come una ricerca binaria o un albero B. Se il numero di voci in ogni directory è relativamente piccolo e l'albero non è molto profondo, l'albero di ricerca binario funzionerebbe bene. Un albero B sarebbe più appropriato per un numero maggiore di file e strutture di directory più profonde.

Di seguito è riportato un esempio di un albero di ricerca binario in Python.

classeNodo:
def__dentro__(sé, valore):

self.valore = valore
self.left_child = Nessuno
self.right_child = Nessuno

classeBinarySearchTree:

def__dentro__(se stesso):
self.root = Nessuno
definserire(sé, valore):

Se self.root ÈNessuno:
self.root = Nodo (valore)

altro:
self._insert (valore, self.root)
def_inserire(self, valore, nodo_corrente):

Se valore < nodo_corrente.valore:
Se current_node.left_child ÈNessuno:
current_node.left_child = Nodo (valore)

altro:
self._insert (valore, current_node.left_child)
elif valore > nodo_corrente.valore:
Se current_node.right_child ÈNessuno:
current_node.right_child = Nodo (valore)
altro:
self._insert (valore, current_node.right_child)

altro:
stampa("Il valore esiste già nell'albero.")
defricerca(sé, valore):
Se self.root ÈnonNessuno:
ritorno self._search (valore, self.root)

altro:
ritornoFalso
def_ricerca(self, valore, nodo_corrente):

Se valore == nodo_corrente.valore:
ritornoVERO

elif valore < nodo_corrente.valore E current_node.left_child ÈnonNessuno:
ritorno self._search (valore, current_node.left_child)

elif valore > nodo_corrente.valore E current_node.right_child ÈnonNessuno:
ritorno self._search (valore, current_node.right_child)

altro:
ritornoFalso

In questa implementazione, costruisci due classi: a BinarySearchTree classe che gestisce le operazioni di inserimento e ricerca e a Nodo classe che simboleggia un nodo nell'albero di ricerca binario.

Mentre il metodo insert inserisce un nuovo nodo nella posizione appropriata nell'albero a seconda del suo valore, il metodo search cerca un nodo con un valore specificato. La complessità temporale di entrambe le operazioni in un albero bilanciato è O(logn).

Selezionare la struttura dati ottimale

La velocità e l'adattabilità della tua applicazione possono essere notevolmente migliorate dalla struttura dei dati che hai scelto. Prendere in considerazione i tuoi dati, le tue operazioni e il tuo ambiente può aiutarti a scegliere la migliore struttura di dati.

Considerazioni come la complessità del tempo, la complessità dello spazio, le operazioni di lettura e scrittura, la concorrenza, il tipo di dati e l'accessibilità della libreria sono importanti.

Valutando il peso di ciascun componente, dovresti scegliere la struttura dati che soddisfa le necessità della tua applicazione.